Text scrolling/ dialogue sounds, per word
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.
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.
-
- Miko-Class Veteran
- Posts: 758
- Joined: Tue Jun 22, 2010 12:54 am
- Completed: Christmas
- IRC Nick: DragoonHP
- Location: Zion Island, Solario
- Contact:
Re: Text scrolling/ dialogue sounds, per word
I tested it out three times after posting the last time, and it's in complete sync for me. And as far as I can see, there is nothing in the code which will make it go out of sync.
I will probablly test it out on a different system just to be sure or maybe OP might help me in testing it. :p
Ah well, it's not a priority in any case.
I will probablly test it out on a different system just to be sure or maybe OP might help me in testing it. :p
Ah well, it's not a priority in any case.
Re: Text scrolling/ dialogue sounds, per word
It shouldn't really be system related so the only thing I can think of that's different and that might matter is the file:
https://www.dropbox.com/s/ye38m6kkhnrrxcr/beep.mp3?dl=0
https://www.dropbox.com/s/ye38m6kkhnrrxcr/beep.mp3?dl=0
-
- Miko-Class Veteran
- Posts: 758
- Joined: Tue Jun 22, 2010 12:54 am
- Completed: Christmas
- IRC Nick: DragoonHP
- Location: Zion Island, Solario
- Contact:
Re: Text scrolling/ dialogue sounds, per word
Perfect sync. This one actually finishes playing off before the next letter is shown :p
EDIT: After repeated testing (I can only hear beeps now), I think there is like a 0.1 sec lag though between the last letter rendering and the sound playing.
EDIT: After repeated testing (I can only hear beeps now), I think there is like a 0.1 sec lag though between the last letter rendering and the sound playing.
-
- Miko-Class Veteran
- Posts: 758
- Joined: Tue Jun 22, 2010 12:54 am
- Completed: Christmas
- IRC Nick: DragoonHP
- Location: Zion Island, Solario
- Contact:
Re: Text scrolling/ dialogue sounds, per word
So finally managed to repeat the bug xela mentioned. It happened for speed > 5
The only change required:
Full code:
The only change required:
Code: Select all
s = re.sub(r"{.+?} ", "", s) # Instead of capturning "{something}" we had to capture "{something} "
Code: Select all
init python:
def check_for_tags(s):
if "{fast}" in s:
s = s.split("{fast}")
s = s[-1]
if "{w" in s:
s = s.replace("{w", " |##")
if "[p" in s:
s = s.replace("{p", " |##")
s = s.replace("}", "} ")
return s
def beepy_voice(event, interact=True, **kwargs):
global _last_beeped_text
if not interact:
return
if event == "show_done":
# Using _last_raw_what makes the callback compatible with extend character.
# Fair warning: _last_raw_what is undocumented and subject to change.
s = _last_raw_what
speed = float(_preferences.text_cps)
if s and speed:
import re
intervals = []
padding = 0
if not _last_beeped_text:
if "{fast}" in s or "{w" in s or "{p" in s:
s = check_for_tags(s)
s = re.sub(r"{.+?} ", "", s) #Instead of capturning "{something}" we had to capture "{something} "
# Whenever we encounter a click-to-continue tag, split the string.
_last_beeped_text = s.split("|##}")
words = _last_beeped_text.pop(0).split()
for w in words:
# If number of seconds is provided, add it to interval.
if "|##=" in w:
try:
padding += int(w[4:-1])
except ValueError:
padding += float(w[4:-1])
continue
if w == "," or w == ".":
intervals[-1] += 1
continue
intervals.append((len(w)+1+padding)/speed) # We add 1 to account for spaces...
renpy.show_screen("silly_timers", intervals, "Button_1.ogg")
elif event == "slow_done":
renpy.hide_screen("silly_timers")
define _last_beeped_text = []
default x = Character("X", callback=beepy_voice)
screen silly_timers(intervals, sfx):
default play_time = 0.001 # We play the very first sound asap.
for i in intervals:
timer play_time action Play("sound", sfx)
$ play_time += i
label start:
x "M, Meow, Meoooooow, Meooooooooooooooooooooow, {fast}..., {color=#F00}fs{w}mfeofmfo{/color}, didsnfsdnfdisf, nsdfnds nfsdicd."
x "M, Meow, Meo00000w, Meo00000000000000000000w"
Re: Text scrolling/ dialogue sounds, per word
Yeap, that's far better, if there are any "special" cases remaining, they should be added by the users. This can be used to make near perfectly synced mouth movements and/or sounds.
-
- Miko-Class Veteran
- Posts: 758
- Joined: Tue Jun 22, 2010 12:54 am
- Completed: Christmas
- IRC Nick: DragoonHP
- Location: Zion Island, Solario
- Contact:
Re: Text scrolling/ dialogue sounds, per word
Found a bug.
So the final code should be
Code: Select all
if w == "," or w == ".":
intervals[-1] += 1/speed # Previously, we always added a second in this case
continue
Code: Select all
init python:
def check_for_tags(s):
if "{fast}" in s:
s = s.split("{fast}")
s = s[-1]
if "{w" in s:
s = s.replace("{w", " |##")
if "[p" in s:
s = s.replace("{p", " |##")
s = s.replace("}", "} ")
return s
def beepy_voice(event, interact=True, **kwargs):
global _last_beeped_text
if not interact:
return
if event == "show_done":
# Using _last_raw_what makes the callback compatible with extend character.
# Fair warning: _last_raw_what is undocumented and subject to change.
s = _last_raw_what
speed = float(_preferences.text_cps)
if s and speed:
import re
intervals = []
padding = 0
if not _last_beeped_text:
if "{fast}" in s or "{w" in s or "{p" in s:
s = check_for_tags(s)
s = re.sub(r"{.+?} ", "", s) #Instead of capturning "{something}" we had to capture "{something} "
# Whenever we encounter a click-to-continue tag, split the string.
_last_beeped_text = s.split("|##}")
words = _last_beeped_text.pop(0).split()
for w in words:
if w == "," or w == ".":
intervals[-1] += 1/speed
continue
# If number of seconds is provided, add it to interval.
if "|##=" in w:
padding += float(w[4:-1])
continue
intervals.append((len(w)+1+padding)/speed) # We add 1 to account for spaces...
renpy.show_screen("silly_timers", intervals, "Button_1.ogg")
elif event == "slow_done":
renpy.hide_screen("silly_timers")
define _last_beeped_text = []
default x = Character("X", callback=beepy_voice)
screen silly_timers(intervals, sfx):
default play_time = 0.001 # We play the very first sound asap.
for i in intervals:
timer play_time action Play("sound", sfx)
$ play_time += i
label start:
x "M, Meow, Meoooooow, Meooooooooooooooooooooow, {fast}..., {color=#F00}fs{w}mfeofmfo{/color}, didsnfsdnfdisf, nsdfnds nfsdicd."
x "M, Meow, Meo00000w, Meo00000000000000000000w"
- Kinmoku
- Miko-Class Veteran
- Posts: 591
- Joined: Mon Aug 11, 2014 9:39 am
- Completed: One Night Stand
- Projects: VIDEOVERSE
- Tumblr: gamesbykinmoku
- itch: kinmoku
- Location: Germany
- Contact:
Re: Text scrolling/ dialogue sounds, per word
Wow guys, this is really amazing! I'm going to try and implement it into my game once I finish what I'm working on
Re: Text scrolling/ dialogue sounds, per word
Hello, I bump this thread a bit because I tried this approach as well, and I changed some things.
A problem I had was that this line yielded None
And I had to hard-code the value. I'm not sure why.
At any rate, I coded a variant of the code that beeps for each character, instead of each word. The algorithm is essentially the same, ignoring tags, commas, dots and spaces.
I also extracted the callback in another generic function, to facilitate changing the sfx...
Code: Select all
if "[p" in s:
s = s.replace("{p", " |##")
should really be
if "{p" in s:
s = s.replace("{p", " |##")
Code: Select all
speed = float(_preferences.text_cps)
At any rate, I coded a variant of the code that beeps for each character, instead of each word. The algorithm is essentially the same, ignoring tags, commas, dots and spaces.
I also extracted the callback in another generic function, to facilitate changing the sfx...
Code: Select all
def beepy_voice_zelda(event, interact=True, **kwargs):
beepy_voice_internal( event, interact, "LTTP_Text_Letter.wav")
def check_for_tags(s):
# {fast} short-circuits the gradual talk, printing it "now"
# Anything before a {fast} must therefor be removed
if "{fast}" in s:
s = s.split("{fast}")
s = s[-1]
# These will be used for padding (they give a time during which the text will stop)
if "{w" in s:
s = s.replace("{w", " |##")
if "{p" in s:
s = s.replace("{p", " |##")
s = s.replace("}", "} ")
return s
def beepy_voice_internal(event, interact, sfx):
global _last_beeped_text
if not interact:
return
if event == "show_done":
# Using _last_raw_what makes the callback compatible with extend character.
# Fair warning: _last_raw_what is undocumented and subject to change.
s = _last_raw_what
speed = float(_preferences.text_cps)
sfx = beepy_voice_theSfx
if s and speed:
import re
intervals = []
padding = 0
if not _last_beeped_text:
if "{fast}" in s or "{w" in s or "{p" in s:
s = check_for_tags(s)
s = re.sub(r"{.+?} ", "", s) #Instead of capturning "{something}" we had to capture "{something} "
# Whenever we encounter a click-to-continue tag, split the string.
_last_beeped_text = s.split("|##}")
#words = _last_beeped_text.pop(0).split() # We don't use words anymore!!!
characters = _last_beeped_text.pop(0)
i = 0
while i < len( characters ):
# If number of seconds is provided, add it to interval.
if characters[i:].startswith( "|##=" ) :
i += 4
sizeOfNumber = 0;
while characters[i + sizeOfNumber] in "0123456789,." :
sizeOfNumber += 1;
try:
padding += int(characters[i:i + sizeOfNumber])
except ValueError:
padding += float(characters[i:i + sizeOfNumber])
i += sizeOfNumber
continue
if characters[i] in ",. ":
if ( intervals ) : # not empty
intervals[-1] += 1/speed
else:
padding += 1
i += 1;
continue
intervals.append((1+padding)/speed)
padding = 0;
i += 1;
renpy.show_screen("silly_timers", intervals, sfx)
elif event == "slow_done":
renpy.hide_screen("silly_timers")
define _last_beeped_text = []
screen silly_timers(intervals, sfx):
default play_time = 0.001 # We play the very first sound asap.
for i in intervals:
timer play_time action Play("sound", sfx)
$ play_time += i
- Kinmoku
- Miko-Class Veteran
- Posts: 591
- Joined: Mon Aug 11, 2014 9:39 am
- Completed: One Night Stand
- Projects: VIDEOVERSE
- Tumblr: gamesbykinmoku
- itch: kinmoku
- Location: Germany
- Contact:
Re: Text scrolling/ dialogue sounds, per word
DragoonHP wrote:Found a bug.
So the final code should beCode: Select all
if w == "," or w == ".": intervals[-1] += 1/speed # Previously, we always added a second in this case continue
Code: Select all
init python: def check_for_tags(s): if "{fast}" in s: s = s.split("{fast}") s = s[-1] if "{w" in s: s = s.replace("{w", " |##") if "[p" in s: s = s.replace("{p", " |##") s = s.replace("}", "} ") return s def beepy_voice(event, interact=True, **kwargs): global _last_beeped_text if not interact: return if event == "show_done": # Using _last_raw_what makes the callback compatible with extend character. # Fair warning: _last_raw_what is undocumented and subject to change. s = _last_raw_what speed = float(_preferences.text_cps) if s and speed: import re intervals = [] padding = 0 if not _last_beeped_text: if "{fast}" in s or "{w" in s or "{p" in s: s = check_for_tags(s) s = re.sub(r"{.+?} ", "", s) #Instead of capturning "{something}" we had to capture "{something} " # Whenever we encounter a click-to-continue tag, split the string. _last_beeped_text = s.split("|##}") words = _last_beeped_text.pop(0).split() for w in words: if w == "," or w == ".": intervals[-1] += 1/speed continue # If number of seconds is provided, add it to interval. if "|##=" in w: padding += float(w[4:-1]) continue intervals.append((len(w)+1+padding)/speed) # We add 1 to account for spaces... renpy.show_screen("silly_timers", intervals, "Button_1.ogg") elif event == "slow_done": renpy.hide_screen("silly_timers") define _last_beeped_text = [] default x = Character("X", callback=beepy_voice) screen silly_timers(intervals, sfx): default play_time = 0.001 # We play the very first sound asap. for i in intervals: timer play_time action Play("sound", sfx) $ play_time += i label start: x "M, Meow, Meoooooow, Meooooooooooooooooooooow, {fast}..., {color=#F00}fs{w}mfeofmfo{/color}, didsnfsdnfdisf, nsdfnds nfsdicd." x "M, Meow, Meo00000w, Meo00000000000000000000w"
I tried putting this in but the sound keeps repeating once the text has finished. Am I missing something? I used this exact code in a new project.
Otherwise, when the text rolls out, it works fantastic! It inspires me to make a typewriter VN
Re: Text scrolling/ dialogue sounds, per word
Nope, it still works for me... you can improve this a lot by adding sounds of different duration depending on length of the text fragment and you can do a damn near perfect lip-syncing using this method if you can handle UDDs.
You make have overwritten default setting for sound channel in your project or are using a sound file of a long duration. Maybe some other weird thing... but it is still working for me under 6.11.
You make have overwritten default setting for sound channel in your project or are using a sound file of a long duration. Maybe some other weird thing... but it is still working for me under 6.11.
Re: Text scrolling/ dialogue sounds, per word
TamaYoshi wrote: ↑Fri Sep 02, 2016 8:11 am Hello, I bump this thread a bit because I tried this approach as well, and I changed some things.
A problem I had was that this line yielded NoneCode: Select all
if "[p" in s: s = s.replace("{p", " |##") should really be if "{p" in s: s = s.replace("{p", " |##")
And I had to hard-code the value. I'm not sure why.Code: Select all
speed = float(_preferences.text_cps)
At any rate, I coded a variant of the code that beeps for each character, instead of each word. The algorithm is essentially the same, ignoring tags, commas, dots and spaces.
I also extracted the callback in another generic function, to facilitate changing the sfx...
Code: Select all
def beepy_voice_zelda(event, interact=True, **kwargs): beepy_voice_internal( event, interact, "LTTP_Text_Letter.wav") def check_for_tags(s): # {fast} short-circuits the gradual talk, printing it "now" # Anything before a {fast} must therefor be removed if "{fast}" in s: s = s.split("{fast}") s = s[-1] # These will be used for padding (they give a time during which the text will stop) if "{w" in s: s = s.replace("{w", " |##") if "{p" in s: s = s.replace("{p", " |##") s = s.replace("}", "} ") return s def beepy_voice_internal(event, interact, sfx): global _last_beeped_text if not interact: return if event == "show_done": # Using _last_raw_what makes the callback compatible with extend character. # Fair warning: _last_raw_what is undocumented and subject to change. s = _last_raw_what speed = float(_preferences.text_cps) sfx = beepy_voice_theSfx if s and speed: import re intervals = [] padding = 0 if not _last_beeped_text: if "{fast}" in s or "{w" in s or "{p" in s: s = check_for_tags(s) s = re.sub(r"{.+?} ", "", s) #Instead of capturning "{something}" we had to capture "{something} " # Whenever we encounter a click-to-continue tag, split the string. _last_beeped_text = s.split("|##}") #words = _last_beeped_text.pop(0).split() # We don't use words anymore!!! characters = _last_beeped_text.pop(0) i = 0 while i < len( characters ): # If number of seconds is provided, add it to interval. if characters[i:].startswith( "|##=" ) : i += 4 sizeOfNumber = 0; while characters[i + sizeOfNumber] in "0123456789,." : sizeOfNumber += 1; try: padding += int(characters[i:i + sizeOfNumber]) except ValueError: padding += float(characters[i:i + sizeOfNumber]) i += sizeOfNumber continue if characters[i] in ",. ": if ( intervals ) : # not empty intervals[-1] += 1/speed else: padding += 1 i += 1; continue intervals.append((1+padding)/speed) padding = 0; i += 1; renpy.show_screen("silly_timers", intervals, sfx) elif event == "slow_done": renpy.hide_screen("silly_timers") define _last_beeped_text = [] screen silly_timers(intervals, sfx): default play_time = 0.001 # We play the very first sound asap. for i in intervals: timer play_time action Play("sound", sfx) $ play_time += i
hello I came across this and realised it was exactly what i have been looking for! So i tried it but an error pops up saying sfx = beepy_voice_theSfx is not defined? Am doing something wrong? I did replace the wav with my own ogg, is there anything else I have to replace? I'm sorry if this is a really noob question lol im still a newbie, thanks alot!
Re: Text scrolling/ dialogue sounds, per word
Sorry for necro, but I've found this code and sadly, on 7.3.5, it doesn't seem to work well..
On slowest speed, it only plays the first ever character of each word, and is completely out of sync. I have standard CPS set to 20 in options.rpy, and text speed is set to lowest possible. Can someone help? I am not sure what I am doing wrong :c
This is my script.rpy. Sorry, I am very new to all this.
On slowest speed, it only plays the first ever character of each word, and is completely out of sync. I have standard CPS set to 20 in options.rpy, and text speed is set to lowest possible. Can someone help? I am not sure what I am doing wrong :c
This is my script.rpy. Sorry, I am very new to all this.
Code: Select all
# The script of the game goes in this file.
init python:
def check_for_tags(s):
if "{fast}" in s:
s = s.split("{fast}")
s = s[-1]
if "{w" in s:
s = s.replace("{w", " |##")
if "[p" in s:
s = s.replace("{p", " |##")
s = s.replace("}", "} ")
return s
def beepy_voice(event, interact=True, **kwargs):
global _last_beeped_text
if not interact:
return
if event == "show_done":
# Using _last_raw_what makes the callback compatible with extend character.
# Fair warning: _last_raw_what is undocumented and subject to change.
s = _last_raw_what
speed = float(_preferences.text_cps)
if s and speed:
import re
intervals = []
padding = 0
if not _last_beeped_text:
if "{fast}" in s or "{w" in s or "{p" in s:
s = check_for_tags(s)
s = re.sub(r"{.+?} ", "", s) #Instead of capturning "{something}" we had to capture "{something} "
# Whenever we encounter a click-to-continue tag, split the string.
_last_beeped_text = s.split("|##}")
words = _last_beeped_text.pop(0).split()
for w in words:
# If number of seconds is provided, add it to interval.
if "|##=" in w:
try:
padding += int(w[4:-1])
except ValueError:
padding += float(w[4:-1])
continue
if w == "," or w == ".":
intervals[-1] += 1
continue
intervals.append((len(w)+1+padding)/speed) # We add 1 to account for spaces...
renpy.show_screen("silly_timers", intervals, "audio/bleep_male.wav")
elif event == "slow_done":
renpy.hide_screen("silly_timers")
define _last_beeped_text = []
default x = Character("X", callback=beepy_voice)
screen silly_timers(intervals, sfx):
default play_time = 0.001 # We play the very first sound asap.
for i in intervals:
timer play_time action Play("sound", sfx)
$ play_time += i
# Declare characters used by this game. The color argument colorizes the
# name of the character.
# The game starts here.
define flash = Fade(0.1, 0.0, 0.1, color="#FFFFFF")
image MH = "MarcusH.jpg"
image MS = "MarcusS.jpg"
image kitchen = "kitchen.JPG"
define w = Character('Wolf', color="#FFFFFF", outlines=[(1, "#39637F", 0, 0)], who_size = 30, what_color="#FFFFFF", callback=beepy_voice)
define m = Character('Marcus', color="#FFFFFF", outlines=[(1, "#39637F", 0, 0)], what_color="#FFb448", who_size = 30, callback=beepy_voice)
label start:
scene kitchen
# This shows a character sprite. A placeholder is used, but you can
# replace it by adding a file named "eileen happy.png" to the images
# directory.
show MH
# These display lines of dialogue.
m "How are you,{w=0.15} Wolf?"
# speech blip here
w "Yeah,{w=0.15} I am fine.{w=0.2} I just got done doing some stuff."
m "ohhh like what?"
w "Playing a game."
show MS with flash
with Shake((0, 0, 0, 0), 1.0, dist=85)
m "YOU WHATTT!!!"
# This ends the game.
return
Re: Text scrolling/ dialogue sounds, per word
You did nothing wrong, but since 2016 stuff changed a lot - now text is tied to voicing and auto-voicing tags and not speaking you can now create your own tags... This code will never work anymore.
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
10 ? "RENPY"
20 GOTO 10
RUN
Re: Text scrolling/ dialogue sounds, per word
The code actually still works for me on 7.3.5 and on 7.4.2. However, it seems to be causing noticable performance issues (Heavy FPS drops). RenpyTom said, that timers, that play audio files multiple times per second isn't really a supported case. Does anybody have an idea how to fix the code accordingly?
Edit: While the code strains the peroformance a little bit, it wasn't as bad as I thought. It doesn't cause that much performance issues after all
Last edited by Okapi on Thu Mar 25, 2021 4:44 pm, edited 1 time in total.
Re: Text scrolling/ dialogue sounds, per word
The problem is that it's desynchronising when using per-character bleeping. I wonder, is there a way to synchronise it?
Who is online
Users browsing this forum: Google [Bot], Lucyper