Use this space for questions related to what you're learning. For any other type of support (website, learning platform, payments, etc...) please get in touch using the contact form.
On the Multiple Voice ChallengePewskeepskiI achieved it without an additional AudioStreamPlayer. I simply assigned current_item["voice"] to the audio_stream_player.stream, after creating an additional "voice" dictionary and adding it to all of the dialogue. This seems to work just fine.66May. 28, 2024
My solution to the multiple voices challengeAceThis is what I came up with to solve the challenge. I ended up with a dictionary inside of a dictionary inside of an array.
```gdscript
extends Control
@onready var rich_text_label: RichTextLabel = %RichTextLabel
@onready var next_button: Button = %NextButton
@onready var back_button: Button = %NextButton2
@onready var audio_stream_player: AudioStreamPlayer = %AudioStreamPlayer
@onready var body: TextureRect = %Body
@onready var expression: TextureRect = %Expression
var bodies : Dictionary = {
"sophia" : {
"texture": preload("res://assets/sophia.png"),
"voice": preload("res://assets/talking_synth.mp3"),
},
"pink" : {
"texture": preload("res://assets/pink.png"),
"voice": preload("res://assets/talking_synth_alternate.ogg"),
}
}
var expressions := {
"regular": preload("res://assets/emotion_regular.png"),
"happy": preload("res://assets/emotion_happy.png"),
"sad": preload("res://assets/emotion_sad.png"),
"angry": preload("res://assets/extras/emotion_angry.png")
}
var dialogue_items : Array[Dictionary] = [
{
"expression": expressions["regular"],
"text": "I'm learning about Arrays...",
"character": bodies["sophia"],
},
{
"expression": expressions["regular"],
"text": "How is that going?",
"character": bodies["pink"],
},
{
"expression": expressions["sad"],
"text": "It's a little bit coplicated.",
"character": bodies["sophia"],
},
{
"expression": expressions["regular"],
"text": "Tell me what you know so far.",
"character": bodies["pink"],
},
{
"expression": expressions["happy"],
"text": "Let's see if I got it right: an array is not a list of values!",
"character": bodies["sophia"],
},
{
"expression": expressions["sad"],
"text": "...",
"character": bodies["pink"],
},
{
"expression": expressions["happy"],
"text": "Did I get it right? Did I?",
"character": bodies["sophia"],
},
{
"expression": expressions["sad"],
"text": "No.",
"character": bodies["pink"],
},
{
"expression": expressions["angry"],
"text": "Dang it!",
"character": bodies["sophia"],
},
]
var current_item_index := 0
func show_text() -> void:
var current_item := dialogue_items[current_item_index]
rich_text_label.text = current_item["text"]
expression.texture = current_item["expression"]
rich_text_label.visible_ratio = 0.0
var tween := create_tween()
var text_appearing_duration : float = current_item["text"].length() / 30.0
tween.tween_property(rich_text_label, "visible_ratio", 1.0, text_appearing_duration)
audio_stream_player.stream = current_item["character"]["voice"]
var sound_max_length : float = audio_stream_player.stream.get_length() - text_appearing_duration
var sound_start_position := randf() * sound_max_length
audio_stream_player.play(sound_start_position)
tween.finished.connect(audio_stream_player.stop)
body.texture = current_item["character"]["texture"]
slide_in()
```
44Aug. 12, 2024
Text Speed Challenge Solutionintent-mantis```gdscript
...
rich_text_label.visible_ratio=0.0
var tween := create_tween()
#the dialog will appear at a rate of 30 characters per second
var tween_time:float = rich_text_label.get_total_character_count()/30.0
#minimum tween time will be 0.5 seconds
if tween_time<0.5:tween_time=0.5
...
tween.tween_property(rich_text_label,"visible_ratio",1,tween_time)
...
```
Here is the solution I had for the text speed challenge. It is very similar to your solution, but I added a minimum for the tween time that I think works better if the dialog is very short.13May. 20, 2024
Solution to the voice challenge! (Not a question)Abdul Hannan AhmedHi!
Here's how I came up with a solution to the voice challenge!
```gdscript
extends Control
@onready var rich_text_label: RichTextLabel = %RichTextLabel
@onready var next_button: Button = %NextButton
@onready var back_button: Button = %BackButton
@onready var audio_stream_player: AudioStreamPlayer = $AudioStreamPlayer
@onready var body: TextureRect = %Body
@onready var expression: TextureRect = %Expression
var bodies := {
"sophia": preload("res://assets/sophia.png"),
"pink": preload("res://assets/pink.png"),
}
var voices := {
"sophia": preload("res://assets/talking_synth.mp3"),
"pink": preload("res://assets/talking_synth_alternate.ogg")
}
var expressions := {
"happy": preload("res://assets/emotion_happy.png"),
"regular": preload("res://assets/emotion_regular.png"),
"sad": preload("res://assets/emotion_sad.png"),
"angry": preload("res://assets/extras/emotion_angry.png"),
}
var dialogue_items: Array[Dictionary] = [
{
"expression": expressions["regular"],
"character": bodies["sophia"],
"text": "Are you a feminist?",
"sound": voices["sophia"]
},
{
"expression": expressions["happy"],
"character": bodies["pink"],
"text": "Yes!",
"sound": voices["pink"]
},
{
"expression": expressions["regular"],
"character": bodies["sophia"],
"text": "What's the difference between a feminist and a knife?",
"sound": voices["sophia"]
},
{
"expression": expressions["regular"],
"character": bodies["pink"],
"text": "What do you mean?",
"sound": voices["pink"]
},
{
"expression": expressions["regular"],
"character": bodies["sophia"],
"text": "I just said what's the difference between a feminist and a knife?",
"sound": voices["sophia"]
},
{
"expression": expressions["sad"],
"character": bodies["pink"],
"text": "Is that even a question???",
"sound": voices["pink"]
},
{
"expression": expressions["happy"],
"character": bodies["sophia"],
"text": "At least the knife has a point",
"sound": voices["sophia"]
},
{
"expression": expressions["angry"],
"character": bodies["pink"],
"text": "😡😡😡😡😡",
"sound": voices["pink"]
},
]
## Holds the index of the currently displayed text.
var current_item_index: int = 0
func _ready() -> void:
show_text()
next_button.pressed.connect(advance)
back_button.pressed.connect(go_back)
func show_text() -> void:
var current_item := dialogue_items[current_item_index]
var tween := create_tween()
var duration: float = current_item["text"].length() / 30.0
expression.texture = current_item["expression"]
body.texture = current_item["character"]
rich_text_label.text = current_item["text"]
slide_character()
rich_text_label.visible_ratio = 0.0
audio_stream_player.stream = current_item["sound"]
var maximum_sound_offset: float = audio_stream_player.stream.get_length() - duration
var sound_start_position: float = maximum_sound_offset * randf()
audio_stream_player.play(sound_start_position)
tween.tween_property(rich_text_label, "visible_ratio", 1.0, duration)
tween.finished.connect(audio_stream_player.stop)
func advance() -> void:
current_item_index += 1
if current_item_index == dialogue_items.size():
current_item_index = 0
show_text()
func go_back() -> void:
current_item_index -= 1
if current_item_index <= 0:
get_tree().quit()
show_text()
func slide_character() -> void:
body.modulate.a = 0.0
body.position.x = 200.0
var tween := create_tween()
var duration := 0.5
tween.set_trans(Tween.TRANS_QUART)
tween.set_ease(Tween.EASE_OUT)
tween.tween_property(body, "position:x", 0.0, duration)
tween.parallel().tween_property(body, "modulate:a", 1.0, duration)
```11Sep. 10, 2024
My solution to different voiceVilldarI've used the same AudioStreamPlayer, I've only changed the stream value based on character. The only issue I have is the alternative voice is a little bit to low. Don't know if there's a way to loud it a little bit. Anyway here my code:
```gdscript
@onready var audio_stream_player: AudioStreamPlayer = %AudioStreamPlayer
var voices := {
"sophia_voice" : preload("res://assets/talking_synth.mp3"),
"pink_voice" : preload("res://assets/talking_synth_alternate.ogg")
}
var dialogue_items : Array[Dictionary] = [
{
"expression" : expressions["regular"],
"text" : "I'm learning about Arrays...",
"character" : bodies["sophia"],
"voice" : voices["sophia_voice"]
},
{
"expression" : expressions["sad"],
"text" : "...and it is a little bit complicated.",
"character" : bodies["pink"],
"voice" : voices["pink_voice"]
},
------
]
func show_text() -> void:
------
audio_stream_player.stream = current_item["voice"]
var sound_max_length = audio_stream_player.stream.get_length() - tween_appearence_duration
var sound_start_position = randf() * sound_max_length
audio_stream_player.play(sound_start_position)
-----
```21May. 31, 2024
FootgunFlatwaterThe Footgun entry in the glossary footgunned itself! :)
In the code example:
```javascript
@onready var line_edit_1 := $LineEdit
@onready var line_edit_2 := $LineEdit2
func add() -> void:
var number_1 := line_edit_1.text()
var number_2 := line_edit_1.text()
var result := number_1 + number_2
print(result)
```
Line 6 should probably be:
```javascript
var number_2 := line_edit_2.text()
```10Nov. 11, 2024
My solution to character voicesPurpleSunriseHello, just posting my solution to character voices. It's very simple. I just added another dictionary with the voice files and assigned each voice to each dictionary in the array. Finally I added a line to show_text() adding the selected voice to the audio stream player.
```gdscript
extends Control
@onready var audio_stream_player: AudioStreamPlayer = %AudioStreamPlayer
@onready var rich_text_label: RichTextLabel = %RichTextLabel
@onready var next_button: Button = %NextButton
@onready var body: TextureRect = %Body
@onready var expression: TextureRect = %Expression
var bodies : Dictionary = {
"pink": preload("res://assets/pink.png"),
"sophia": preload("res://assets/sophia.png"),
}
var expressions : Dictionary = {
"happy": preload("res://assets/emotion_happy.png"),
"regular": preload("res://assets/emotion_regular.png"),
"sad": preload("res://assets/emotion_sad.png"),
"angry": preload("res://assets/extras/emotion_angry.png"),
}
var voices : Dictionary ={
"pink" : preload("res://assets/talking_synth_alternate.ogg"),
"sophia" : preload("res://assets/talking_synth.ogg"),
}
var dialogue_items : Array [Dictionary] = [
{
"expression": expressions["regular"],
"text": "The path of self-overcoming...",
"character": bodies["pink"],
"character_voice" : voices["pink"],
},
{
"expression": expressions["sad"],
"text": "Is a dance between failur and resilience,",
"character": bodies["sophia"],
"character_voice" : voices["sophia"],
},
{
"expression": expressions["happy"],
"text": "Shaping your best self.",
"character": bodies["pink"],
"character_voice" : voices["pink"],
},
]
var current_item_index := 0
func _ready() -> void:
rich_text_label.visible_ratio = 0.0
show_text()
next_button.pressed.connect(advance)
func show_text() -> void:
var current_item := dialogue_items[current_item_index]
rich_text_label.text = current_item["text"]
expression.texture = current_item["expression"]
body.texture = current_item["character"]
audio_stream_player.stream = current_item["character_voice"]
rich_text_label.visible_ratio = 0.0
var text_appearing_duration := 1.2
var audio_max_lenght := audio_stream_player.stream.get_length() - text_appearing_duration
#var sound_start_position := randf() * audio_max_lenght
#audio_stream_player.play(sound_start_position)
audio_stream_player.play(randf_range(0, audio_max_lenght))
var tween := create_tween()
tween.tween_property(rich_text_label, "visible_ratio", 1.0, text_appearing_duration)
tween.finished.connect(audio_stream_player.stop)
slide_in()
func advance()-> void:
current_item_index += 1
if current_item_index == dialogue_items.size():
get_tree().quit()
else:
show_text()
func slide_in() -> void:
var tween = create_tween().set_trans(Tween.TRANS_QUAD)
tween.set_ease(Tween.EASE_OUT)
body.position.x = 200.0
tween.tween_property(body, "position:x", 0.0, 0.5)
body.modulate.a = 0.0
tween.parallel().tween_property(body, "modulate:a", 1.0, 0.2)
```
Thank you very much for the nice lesson.10Nov. 04, 2024
Several characters are on stage at the same timeram876Hello! In visual games, there is usually more than 1 character on the screen at the same time during dialogues on the stage. I quickly looked at the future lessons and did not notice such an opportunity there. Then I thought about how it could be implemented. Before that, we implemented everything through an array of dictionaries and assumed that it was necessary to implement what we wanted in the same way. In dialogue_items, for each character in each element, you need to define a modulate 0 or 1 for visibility on the stage, the initial and final position values for animation, and in show_text() draw and animate all characters. If two characters have a modulate equal to one, then there will be 2 characters on the screen at the same time, if three, then respectively all three at the same time. If the modulate is 0, then these characters will be hidden. Am I thinking in the right direction or is there something simpler? With this method, it seems to me that resources will be used uneconomically.10Oct. 19, 2024
I have an error line 2 "current_item not declared in current scope"substantial-tarsier```gdscript
func show_text():
var text_duration:float = current_item["text"].length() / 30.0
var current_item = dialogue_items[current_item_index]
var sound_max_length = audio_stream_player_2d.stream.get_length() - text_duration
if current_item_index == dialogue_items.size():
get_tree().quit()
else:
var tween = create_tween()
var sound_start_position= randf() * sound_max_length
rich_text_label.visible_ratio = 0
tween.tween_property(rich_text_label,"visible_ratio",1, text_duration)
tween.finished.connect(kill_audio)
rich_text_label.text = current_item["text"]
expression.texture = current_item["expression"]
body.texture = current_item["character"]
current_item_index += 1
audio_stream_player_2d.play(sound_start_position)
```10Oct. 15, 2024
Another solution for the voice challengedavidakFirst i added a `voices` dictionary like we did with `bodies` and `expressions`:
```gdscript
var voices := {
"default": preload("res://assets/talking_synth.ogg"),
"alternate": preload("res://assets/talking_synth_alternate.ogg"),
}
```
Then, my **first solution** was to add the voices to the `dialogue_items` dictionary, but i did not like to repeat the data which character has which voice so many times, which could lead to errors and less readable code.
```gdscript
{
"text": "Roses are red",
"expression": expressions["regular"],
"character": bodies["sophia"],
"voice": voices["default"],
},
```
I set the `stream` of the `audio_stream_player` we already had to the voice file from the `dialogue_items` dictionary.
```gdscript
audio_stream_player.stream = current_item["voice"]
```
This does work, but is not very elegant.
In my **second solution**, i added the voices dict and this code to `show_text`. This is easier to understand.
```gdscript
if current_item["character"] == bodies["sophia"]:
audio_stream_player.stream = voices["default"]
elif current_item["character"] == bodies["pink"]:
audio_stream_player.stream = voices["alternate"]
```
I think the most elegant solution would be to add the voice file to a `characters` dictionary, like we did with the texture. So all data about the character is in one place and you separate data from logic. Like @Ace did in their solution.10Sep. 18, 2024
Preloading: predict result types?TJBy reading other posts here I was able to solve the challenge of the two voices as well. I am just wondering if we could somehow know what type of object (class) is returned by the `preload()` keyword. Consider for example the following preloads:
```gdscript
preload("res://assets/talking_synth.ogg")
preload("res://assets/talking_synth_alternate.ogg")
```
To me it felt as some kind of luck that we could directly assign the result of these preloads to the `audio_stream_player.stream` property. It might perhaps be better, in terms of acquiring problem-solving skills, if we could know or predict the result type of the preloads and match that to the documentation of the `audio_stream_player`. What is your advice? Is there some kind of look-up table to match resource file extensions to the resulting object types (classes) that preloading makes of them?
Thanks for your help!20Aug. 15, 2024
Defi HazlarHello,
To solve the challenge, I encounter a problem, here is the code:
```gdscript
@onready var audio_stream_player: AudioStreamPlayer = %AudioStreamPlayer
@onready var body: TextureRect = %Body
@onready var expression: TextureRect = %Expression
const PINK := 1
const SOPHIA := 0
var speaker_audio :={
SOPHIA : preload("res://assets/talking_synth.ogg"),
PINK : preload("res://assets/talking_synth_alternate.ogg")
}
var current_speaker := SOPHIA
var current_item_index := 0
func show_text() -> void:
slide_in()
var current_item := dialogue_items[current_item_index]
rich_text_label.text = current_item["text"]
expression.texture = current_item["expression"]
body.texture = current_item["character"]
rich_text_label.visible_ratio = 0.0
var tween := create_tween()
var duration_appearing_txt := 1.2
tween.tween_property(rich_text_label, "visible_ratio", 1, duration_appearing_txt)
audio_stream_player.stream = speaker_audio[current_speaker%2]
var sound_max_length := audio_stream_player.get_length() - duration_appearing_txt
var sound_start_position := randf() * sound_max_length
audio_stream_player.play(sound_start_position)
tween.finished.connect(audio_stream_player.stop)
current_speaker += 1
```
Edit: I modified the code by keeping it and wanting to directly modify the stream property that connects the audio file. And I get several errors:
**In the 'call stack' console:**
*Parser Error: Cannot infer the type of "sound_max_length" variable because the value doesn't have a set type.*
**And in the editor script:**
*Line 108:Cannot infer the type of "sound_max_length" variable because the value doesn't have a set type.*
*Line 109:Cannot infer the type of "sound_start_position" variable because the value doesn't have a set type.*40Aug. 13, 2024
Invalid get index 'regular' (on base: 'Nil').TheEffingLawNot sure why I'm getting this error message on line 13
```gdscript
extends Control
var expressions: Dictionary = {
"happy": preload("res://assets/emotion_happy.png"),
"regular": preload("res://assets/emotion_regular.png"),
"sad": preload("res://assets/emotion_sad.png"),
}
var bodies:= {
"pink": preload("res://assets/pink.png"),
"sophia": preload("res://assets/sophia.png")
}
var dialogue_text: Array[Dictionary] = [
{
"expression": expressions["happy"],
"text": "I'm learning about Arrays and Dictionaries...",
"character": bodies["sophia"],
},
{
"expression" : expression["regular"],
"text" : "That's amazing! How is it coming along?",
"character" : bodies["pink"],
},
{
"expression" : expressions["sad"],
"text" : "it is quite complicated",
"character" : bodies["sophia"],
},
{
"expression" : expressions["regular"],
"text" : "But I won't give up. Practice makes perfect!",
"character" : bodies["sophia"],
},
{
"expression" : expressions["happy"],
"text" : "That's the spirit! You got this!",
"character" : bodies["pink"],
}
]
var current_item_index := 0
@onready var rich_text_label : RichTextLabel = %RichTextLabel
@onready var next_button : Button = %NextButton
@onready var previous_button : Button = %PreviousButton
@onready var audio_stream_player : AudioStreamPlayer = %AudioStreamPlayer
@onready var body: TextureRect = %Body
@onready var expression: TextureRect = %Expression
func _ready() -> void:
next_button.connect("pressed", _advance_text)
previous_button.pressed.connect(_previous_text)
show_text()
func _advance_text() -> void:
current_item_index += 1
show_text()
func _previous_text() -> void:
current_item_index -= 1
show_text()
func show_text() -> void:
var current_item := dialogue_text[current_item_index % dialogue_text.size()]
var text_appearing_duration := 1.0
rich_text_label.text = current_item["text"]
expression.texture = current_item["expression"]
body.texture = current_item["character"]
rich_text_label.visible_ratio = 0.0
var tween = create_tween()
tween.tween_property(rich_text_label,"visible_ratio", 1.0, current_item["text"].length()/30.0)
var max_sound_length = audio_stream_player.stream.get_length() - text_appearing_duration
var sound_start_position = randf() * max_sound_length
audio_stream_player.play(sound_start_position)
tween.finished.connect(audio_stream_player.stop)
slide_in()
func slide_in() -> void:
var tween = create_tween()
tween.set_trans(Tween.TRANS_QUART).set_ease(Tween.EASE_OUT)
body.position.x = 200.0
tween.tween_property(body, "position:x", 0.0, 0.3)
body.modulate.a = 0.0
tween.parallel().tween_property(body, "modulate:a", 1.0, 2.0)
body.scale = Vector2(0.5, 0.5)
tween.parallel().tween_property(body, "scale", Vector2(1.0,1.0), 2.0)
```20Jul. 02, 2024
Function Nikita MyshkinI did not add the function `slide_in()` in `show_text()`
I added in the functions `advance()` and `previous()`Everything works for me. I'm wondering why my option works? And how important is it to add `slide_in()` to `show_text()`?
Here is my code:
```gdscript
extends Control
@onready var rich_text_label: RichTextLabel = %RichTextLabel
@onready var next_button: Button = %NextButton
@onready var previous_button: Button = %PreviousButton
@onready var audio_stream_player: AudioStreamPlayer = %AudioStreamPlayer
@onready var audio_stream_player_pink: AudioStreamPlayer = $AudioStreamPlayerPink
@onready var body: TextureRect = %Body
@onready var expression: TextureRect = %Expression
var expressions := {
"happy": preload("res://assets/emotion_happy.png"),
"regular": preload("res://assets/emotion_regular.png"),
"sad": preload("res://assets/emotion_sad.png"),
"angry": preload("res://assets/extras/emotion_angry.png")
}
var bodies := {
"sophia": preload("res://assets/sophia.png"),
"pink": preload("res://assets/pink.png")
}
var voice := {
"voice_sophia": preload("res://assets/talking_synth.ogg"),
"voice_pink": preload("res://assets/talking_synth_alternate.ogg")
}
var dialogue_items : Array[Dictionary] = [
{
"expression": expressions["regular"],
"text": "I'm learning about Array...",
"character": bodies["pink"],
"voice": voice["voice_pink"]
},
{
"expression": expressions["sad"],
"text": "... and it is a little bit complicated.",
"character": bodies["sophia"],
"voice": voice["voice_sophia"]
},
{
"expression": expressions["happy"],
"text": "I'm happy!",
"character": bodies["pink"],
"voice": voice["voice_pink"]
},
{
"expression": expressions["angry"],
"text": "Шел бы ты нахуй мудила и забери собой свои две сосиски!",
"character": bodies["sophia"],
"voice": voice["voice_sophia"]
},
]
var current_item_index := 0
func _ready() -> void:
show_text()
next_button.pressed.connect(advance)
previous_button.pressed.connect(previous)
previous_button.visible = false
func show_text() -> void:
var current_item := dialogue_items[current_item_index]
rich_text_label.visible_ratio = 0.0
rich_text_label.text = current_item["text"]
expression.texture = current_item["expression"]
body.texture = current_item["character"]
audio_stream_player.stream = current_item["voice"]
audio_stream_player_pink.stream = current_item["voice"]
next_button.visible = current_item_index < dialogue_items.size() - 1
previous_button.visible = current_item_index > 0
var tween := create_tween()
var text_appearing_duration: float = current_item["text"].length() / 20.0
tween.tween_property(rich_text_label, "visible_ratio", 1.0, text_appearing_duration)
var sound_max_lenght_pink := audio_stream_player_pink.stream.get_length() - text_appearing_duration
var sound_start_position_pink := randf() * sound_max_lenght_pink
audio_stream_player_pink.play(sound_start_position_pink)
tween.finished.connect(audio_stream_player_pink.stop)
var sound_max_lenght := audio_stream_player.stream.get_length() - text_appearing_duration
var sound_start_position := randf() * sound_max_lenght
audio_stream_player.play(sound_start_position)
tween.finished.connect(audio_stream_player.stop)
func advance() -> void:
current_item_index = min(current_item_index + 1, dialogue_items.size() - 1)
show_text()
slide_in()
func previous() -> void:
current_item_index = max(current_item_index - 1, 0)
show_text()
slide_in()
func slide_in() -> void:
var tween := create_tween()
tween.set_trans(Tween.TRANS_QUART)
tween.set_ease(Tween.EASE_OUT)
body.position.x = 200.0
tween.tween_property(body, "position:x", 0.0, 1.0)
body.modulate.a = 0.0
tween.parallel().tween_property(body, "modulate:a", 1.0, 1.0)
```10Jul. 01, 2024
What's a footgun?tesfalconThat sounds like a bad translation of a Japanese anime.10Jun. 19, 2024
Make the body slide in only if it change charactertuktuk22i add new variables and if statement to make the body slide only if it change character (body texture).
it works but i curious is there any "better/proper" way to code it ?
```gdscript
# ........
var current_item_index := 0
# new var
var character_name : Dictionary = bodies["sophia"]
var last_character : Dictionary = character_name
func _ready() -> void:
show_text()
slide_in()
next_button.pressed.connect(advance)
func show_text() -> void:
var current_item := dialogue_items[current_item_index]
rich_text_label.text = current_item["text"]
expression.texture = current_item["expression"]
body.texture = current_item["character"]
audio_stream_player.stream = current_item["voice"]
rich_text_label.visible_ratio = 0.0
#new code here
character_name = current_item["character"]
var tween := create_tween()
#var text_appearing_duration := 1.2
var text_appearing_duration : float = current_item["text"].length() / 30.0
var sound_max_length := audio_stream_player.stream.get_length() - text_appearing_duration
var sound_start_position := randf() * sound_max_length
audio_stream_player.play(sound_start_position)
tween.tween_property(rich_text_label,"visible_ratio", 1.0, text_appearing_duration)
tween.finished.connect(audio_stream_player.stop)
func advance() -> void:
# new code here
last_character = character_name
current_item_index += 1
if current_item_index == dialogue_items.size():
get_tree().quit()
else:
show_text()
if last_character != character_name :
slide_in()
func slide_in() -> void:
var tween := create_tween()
tween.set_trans(Tween.TRANS_QUART)
tween.set_ease(Tween.EASE_OUT)
body.position.x = 400.0
body.modulate.a = 0.0
body.scale = Vector2(0.8, 1.1)
tween.tween_property(body, "position:x", 0.0, 0.8)
tween.parallel().tween_property(body, "modulate:a", 1.0, 0.7)
tween.parallel().tween_property(body, "scale", Vector2(1.0, 1.0), 0.7)
```10Jun. 14, 2024
Adding the second voice challenge.AJ StudiosThe second voice is not playing. I'm including here the following lines of code: the `voices dictionary` I created, the lines of code I added to the `var dialogue_items: Array[Dictionary]`, the `@on ready variables` and the lines of code that play the sound under the `func show_text()`
```gdscript
# The voices dictionary I created
var voices := {
"voiceA": preload ("res://assets/talking_synth.mp3"),
"voiceB": preload ("res://assets/talking_synth_alternate.ogg"),
}
# The new additions to the dialogue_items Array
var dialogue_items: Array[Dictionary] = [
{
"character": bodies["sophia"],
"voice": voices["voiceA"],
},
{
"character": bodies["pink"],
"voice": voices["voiceB"],
},
# New @on ready vars
@onready var audio_stream_player_a: AudioStreamPlayer = $AudioStreamPlayerA
@onready var audio_stream_player_b: AudioStreamPlayer = $AudioStreamPlayerB
# I was wondering If I can combine var sound_max_length & var sound_max_length_2
# var sound_start_position & var sound_start_position_2
# That way I don't have to write so much code.
func show_text() -> void:
...
var sound_max_length := audio_stream_player_a.stream.get_length() - text_appearing_duration
var sound_start_position := randf() * sound_max_length
audio_stream_player_a.play(sound_start_position)
# We stop the audio when the text finishes appearing.
tween.finished.connect(audio_stream_player_a.stop)
var sound_max_length_2 := audio_stream_player_b.stream.get_length() - text_appearing_duration
var sound_start_position_2 := randf() * sound_max_length
audio_stream_player_b.play(sound_start_position)
# We stop the audio when the text finishes appearing.
tween.finished.connect(audio_stream_player_b.stop)
```
100May. 30, 2024
Preformance CostStevenWhat is the performance cost of preloading data into a dictionary over and over verses loading when needed? Also, would it be better to have multiple AudioStreamPlayers?
I'm thinking that the most hands-off approach in code would be to include it in the dictionary or have a separate dictionary for audio. I ended up adding audio to the dictionary and using one line of code to play the audio.
audio_stream_player.set_stream(current_item["voice"])10May. 27, 2024
Is my way of handling the "different voice" challenge sub-optimal or otherwise bad?SingleMom420My solution to the challenge of using the alternate voice sound for the other character involved making another AudioStreamPlayer node and then adding a check to `show_text()`:
```gdscript
if current_item["character"] == preload("res://assets/sophia.png"):
audio_stream_player.play(sound_start_position)
else:
audio_stream_player_2.play(sound_start_position)
tween.finished.connect(audio_stream_player.stop)
tween.finished.connect(audio_stream_player_2.stop)
```
This seems to be working as intended, but the hint for the challenge mentioned creating another dictionary with the preloaded sound files, which I did not do. My method seems quicker because I don't have to go back and add a new item to all the dictionaries in the `dialogue_items` array. Is there some disadvantage to my way that I'm not seeing, or is it also acceptable?40May. 17, 2024
Lesson Q&A
Use this space for questions related to what you're learning. For any other type of support (website, learning platform, payments, etc...) please get in touch using the contact form.