Adds commentary to the jellyfish minigame. Reworks the jellyfish pressed interaction. Corrects the stimuli and distractions. Adds the highlight fx to the jellyfishes

This commit is contained in:
Dylan Sarrazyn
2024-04-08 10:06:35 +02:00
committed by BimDav
parent 0b93fa4ca0
commit 6c751f0bf2
10 changed files with 217 additions and 73 deletions
+4
View File
@@ -2,7 +2,11 @@
importer="csv_translation"
type="Translation"
<<<<<<< HEAD
uid="uid://dh6pc6oshep4t"
=======
uid="uid://4yf2petk28t8"
>>>>>>> 75bb22e1 (Adds commentary to the jellyfish minigame. Reworks the jellyfish pressed interaction. Corrects the stimuli and distractions. Adds the highlight fx to the jellyfishes)
[deps]
+3
View File
@@ -86,6 +86,9 @@ func _ready() -> void:
minigame_ui.set_music_volume_slider(UserDataManager.get_music_volume())
minigame_ui.set_voice_volume_slider(UserDataManager.get_voice_volume())
minigame_ui.set_effects_volume_slider(UserDataManager.get_effects_volume())
# Stop the current music
MusicManager.stop()
_reset_logs()
_initialize()
+19 -2
View File
@@ -1,5 +1,6 @@
@tool
extends MarginContainer
class_name Jellyfish
signal pressed()
@@ -27,22 +28,34 @@ const sizes: = [
@onready var animated_sprite: = %AnimatedSprite2D
@onready var label: = %AutoSizeLabel.get_node("Label")
@onready var highlight_fx: = $HighlightFX
@onready var right_fx: = $RightFX
@onready var wrong_fx: = $WrongFX
var stimulus: Dictionary :
set(value):
stimulus = value
label.text = value.Grapheme
if label:
if value.has("Grapheme"):
label.text = value.Grapheme
else:
label.text = ""
func _ready() -> void:
stimulus = stimulus
var f = randf()
color = Colors.Red if f < 0.7 else Colors.Green
animated_sprite.play("idle")
animated_sprite.frame = randi_range(0, animated_sprite.sprite_frames.get_frame_count("idle") - 1)
func is_idle() -> bool:
return animated_sprite.animation == "idle"
func happy() -> void:
animated_sprite.play("happy")
@@ -55,6 +68,10 @@ func hit() -> void:
animated_sprite.play("hit")
func highlight() -> void:
highlight_fx.play()
func right() -> void:
right_fx.play()
await right_fx.finished
@@ -72,6 +89,6 @@ func _on_gui_input(event: InputEvent) -> void:
func delete() -> void:
var tween: = create_tween()
tween.tween_property(self, "modulate:a", 0, 1)
tween.tween_property(self, "modulate:a", 0, 2)
await tween.finished
queue_free()
+13 -6
View File
@@ -1,19 +1,25 @@
[gd_scene load_steps=8 format=3 uid="uid://cpkwyypyikpfc"]
[gd_scene load_steps=9 format=3 uid="uid://cpkwyypyikpfc"]
[ext_resource type="Script" path="res://sources/utils/sprite_control.gd" id="1_1b85n"]
[ext_resource type="Script" path="res://sources/minigames/jellyfish/jellyfish.gd" id="1_06uwq"]
[ext_resource type="PackedScene" uid="uid://cn2rw06pltyiu" path="res://sources/utils/fx/right.tscn" id="2_edt4e"]
[ext_resource type="PackedScene" uid="uid://cge0uyn30tcpv" path="res://sources/utils/fx/highlight.tscn" id="3_5uhvd"]
[ext_resource type="Script" path="res://sources/utils/percent_margin_container.gd" id="3_vllju"]
[ext_resource type="PackedScene" uid="uid://bgio7muqck2bu" path="res://sources/utils/auto_size_label.tscn" id="4_26xiq"]
[ext_resource type="SpriteFrames" uid="uid://dquynn3nx52o" path="res://sources/minigames/jellyfish/red_jellyfish_animations.tres" id="4_g5og8"]
[ext_resource type="SpriteFrames" uid="uid://dquynn3nx52o" path="res://sources/minigames/jellyfish/red_jellyfish_animations.tres" id="4_d8s11"]
[ext_resource type="PackedScene" uid="uid://dlmbxcgiv8tpr" path="res://sources/utils/fx/wrong.tscn" id="6_w1tlu"]
[node name="Jellyfish" type="MarginContainer"]
custom_minimum_size = Vector2(449.43, 449.43)
custom_minimum_size = Vector2(466.955, 466.955)
offset_right = 200.0
offset_bottom = 200.0
script = ExtResource("1_06uwq")
[node name="HighlightFX" parent="." instance=ExtResource("3_5uhvd")]
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 4
[node name="RightFX" parent="." instance=ExtResource("2_edt4e")]
position = Vector2(284, 142.25)
@@ -25,9 +31,10 @@ sprites = [NodePath("AnimatedSprite2D")]
[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="SpriteControl"]
unique_name_in_owner = true
scale = Vector2(1e-05, 1e-05)
sprite_frames = ExtResource("4_g5og8")
scale = Vector2(2.50538, 2.50538)
sprite_frames = ExtResource("4_d8s11")
animation = &"idle"
frame_progress = 0.106154
centered = false
[node name="PercentMarginContainer" type="Container" parent="."]
@@ -46,7 +53,7 @@ unique_name_in_owner = true
layout_mode = 2
[node name="Label" parent="PercentMarginContainer/AspectRatioContainer/AutoSizeLabel" index="0"]
text = "A"
text = ""
[node name="WrongFX" parent="." instance=ExtResource("6_w1tlu")]
position = Vector2(284, 142.25)
+146 -55
View File
@@ -14,69 +14,99 @@ class DifficultySettings:
var difficulty_settings: = {
0: DifficultySettings.new(4, 0.6, 150),
1: DifficultySettings.new(3, 0.5, 175),
2: DifficultySettings.new(2, 0.4, 200),
3: DifficultySettings.new(1, 0.3, 250),
4: DifficultySettings.new(1, 0.2, 300),
0: DifficultySettings.new(4, 0.75, 150),
1: DifficultySettings.new(3, 0.66, 175),
2: DifficultySettings.new(2, 0.33, 200),
3: DifficultySettings.new(1, 0.25, 250),
4: DifficultySettings.new(1, 0.25, 300),
}
@export var lesson_nb: = 4
@export var difficulty: = 0
var blocking_jellyfish: Array[Control] = []
var blocking_jellyfish: Array[Jellyfish] = []
@onready var spawning_space: Control = %SpawningSpace
@onready var spawn_timer: = $SpawnTimer
# Find the stimuli and distractions of the minigame.
func _find_stimuli_and_distractions() -> void:
stimuli = Database.get_GP_for_lesson(lesson_nb, true)
var all_distractions: = Database.get_GP_before_lesson(lesson_nb, true)
all_distractions.shuffle()
var number_of_distractions: int = min((max_progression - 1) / 2, all_distractions.size())
var current_distractions: = all_distractions.slice(0, number_of_distractions)
# Gets the stimuli (only vowels for now) for the current lesson
var current_lesson_stimuli = Database.get_vowels_for_lesson(lesson_nb)
stimuli.append_array(current_distractions)
distractions = stimuli.duplicate()
# Calculate the number of stimuli to add from this lesson (70% of the maximum progression)
@warning_ignore("narrowing_conversion")
var number_of_stimuli: int = max_progression * 0.7
# Adds the right number of stimuli from current lesson
while stimuli.size() < number_of_stimuli:
stimuli.append(current_lesson_stimuli[randi() % current_lesson_stimuli.size()])
# Gets other stimuli from previous errors or lessons
var previous_lesson_stimuli = Database.get_vowels_before_lesson(lesson_nb)
while stimuli.size() < max_progression:
stimuli.append(previous_lesson_stimuli[randi() % previous_lesson_stimuli.size()])
# Shuffle the stimuli
stimuli.shuffle()
# For each stimuli get the distractors
var all_learned_stimuli = previous_lesson_stimuli
all_learned_stimuli.append_array(current_lesson_stimuli)
for stimulus in stimuli:
var stimulus_distractors := []
for distractor in all_learned_stimuli:
if stimulus.Grapheme != distractor.Grapheme and stimulus.Phoneme != distractor.Phoneme:
stimulus_distractors.append(distractor)
# Adds fake distractors (allow to have empty jellyfishes) if there are less than 4 distractors
while stimulus_distractors.size() < 4:
stimulus_distractors.append({})
distractions.append(stimulus_distractors)
print(stimuli)
print(distractions)
# Launch the minigame
func _start() -> void:
super()
audio_player.stream = Database.get_audio_stream_for_phoneme(stimuli[current_progression % stimuli.size()].Phoneme)
audio_player.play()
_play_current_stimulus_phoneme()
spawn_timer.start()
func _on_spawn_timer_timeout() -> void:
_spawn()
spawn_timer.wait_time = _get_difficulty_settings().spawn_time
func _process(delta: float) -> void:
for jellyfish: Control in spawning_space.get_children():
jellyfish.position.y -= _get_difficulty_settings().velocity * delta
for jellyfish: Jellyfish in spawning_space.get_children():
# Moves the jellyfish upward
if jellyfish.is_idle():
jellyfish.position.y -= _get_difficulty_settings().velocity * delta
# Handles the blocking array
if jellyfish in blocking_jellyfish and jellyfish.position.y + jellyfish.size.y < spawning_space.size.y:
blocking_jellyfish.erase(jellyfish)
# Destroy the jellyfish when it leaves the screen
if jellyfish.position.y + jellyfish.size.y < 0:
jellyfish.queue_free()
func _get_difficulty_settings() -> DifficultySettings:
return difficulty_settings[difficulty]
func _highlight():
# TODO Revoir, il faut highlight les méduses jusqu'à ce que la bonne réponse soit trouvée ? Ou pendant un certain temps ? Ou on laisse comme ça ?
for jellyfish: Jellyfish in spawning_space.get_children():
if jellyfish.stimulus and jellyfish.stimulus.Grapheme == _get_current_stimulus().Grapheme:
jellyfish.highlight()
func _spawn() -> void:
var new_jellyfish: = jellyfish_scene.instantiate()
spawning_space.add_child(new_jellyfish)
var is_stimulus: = randf() < _get_difficulty_settings().stimuli_ratio
new_jellyfish.stimulus = stimuli[current_progression % stimuli.size()] if is_stimulus else stimuli[randi() % stimuli.size()]
# Instantiate a new jellyfish
var new_jellyfish : Jellyfish = jellyfish_scene.instantiate()
# Check if there is enough space to spawn the jellyfish and find a spot
var permitted_range: = 0
var left_border: = 0
# blocking jellyfish is supposed to be ordered
# Blocking jellyfish is supposed to be ordered
for blocking in blocking_jellyfish:
permitted_range += max(0, blocking.position.x - left_border - new_jellyfish.size.x)
left_border = blocking.position.x + blocking.size.x
@@ -84,9 +114,19 @@ func _spawn() -> void:
if permitted_range <= 0:
new_jellyfish.queue_free()
return
# Define if the jellyfish is a stimulus or a distraction
var is_stimulus: = randf() < _get_difficulty_settings().stimuli_ratio
if is_stimulus:
new_jellyfish.stimulus = _get_current_stimulus()
else:
var current_distractors : Array = distractions[current_progression % distractions.size()]
new_jellyfish.stimulus = current_distractors[randi() % current_distractors.size()]
# Randomize the spawn and adds the jellyfish into the scene
var random_spawn: = randi_range(0, permitted_range - 1)
left_border = 0
# blocking jellyfish is supposed to be ordered
# Blocking jellyfish is supposed to be ordered
for blocking in blocking_jellyfish:
var local_permitted_range = max(0, blocking.position.x - left_border - new_jellyfish.size.x)
if local_permitted_range <= random_spawn:
@@ -96,6 +136,8 @@ func _spawn() -> void:
left_border = blocking.position.x + blocking.size.x
new_jellyfish.position.x = left_border + random_spawn
new_jellyfish.position.y = spawning_space.size.y
# Insert the new jellyfish on the right spot in the blocking array
var found_ind: = -1
for i in blocking_jellyfish.size():
var blocking: = blocking_jellyfish[i]
@@ -105,21 +147,65 @@ func _spawn() -> void:
if found_ind < 0:
found_ind = blocking_jellyfish.size()
blocking_jellyfish.insert(found_ind, new_jellyfish)
# Connects the new jellyfish with the pressed signal
new_jellyfish.pressed.connect(_on_jellyfish_pressed.bind(new_jellyfish))
# Adds the jellyfish into the scene
spawning_space.add_child(new_jellyfish)
func _on_jellyfish_pressed(jellyfish: Control) -> void:
# already clicked
_log_new_response(jellyfish.stimulus, stimuli[current_progression % stimuli.size()])
if jellyfish.get_parent() != spawning_space:
func _get_difficulty_settings() -> DifficultySettings:
return difficulty_settings[difficulty]
func _get_current_stimulus() -> Dictionary :
if stimuli.size() == 0:
return {}
return stimuli[current_progression % stimuli.size()]
# TODO Peut être à déplacer dans un script attaché à l'AudioStreamPlayer de BaseMinigame
func _play_phoneme(phoneme : String) -> void:
var phoneme_audiostream = Database.get_audio_stream_for_phoneme(phoneme) as AudioStream
if not phoneme_audiostream:
push_warning("AudioStream not found for phoneme " + phoneme)
return
var jellyfish_position: = jellyfish.global_position
spawning_space.remove_child(jellyfish)
spawning_space.add_sibling(jellyfish)
jellyfish.global_position = jellyfish_position
var is_right: = false
if jellyfish.stimulus == stimuli[current_progression % stimuli.size()]:
is_right = true
audio_player.stream = phoneme_audiostream
audio_player.play()
if audio_player.playing:
await audio_player.finished
func _play_current_stimulus_phoneme()-> void:
var current_stimulus: = _get_current_stimulus()
if not current_stimulus or not current_stimulus.has("Phoneme"):
return
await _play_phoneme(current_stimulus.Phoneme)
# ------------ Connections ------------
func _on_spawn_timer_timeout() -> void:
_spawn()
spawn_timer.wait_time = _get_difficulty_settings().spawn_time
func _on_jellyfish_pressed(jellyfish: Jellyfish) -> void:
# Disconnect the jellyfish
jellyfish.pressed.disconnect(_on_jellyfish_pressed)
# Log the answer
_log_new_response(jellyfish.stimulus, _get_current_stimulus())
# Check if the stimulus is right
var is_right: bool = jellyfish.stimulus.Grapheme == _get_current_stimulus().Grapheme
if is_right:
jellyfish.happy()
jellyfish.right()
current_progression += 1
@@ -127,25 +213,30 @@ func _on_jellyfish_pressed(jellyfish: Control) -> void:
jellyfish.hit()
jellyfish.wrong()
current_lives -= 1
audio_player.stream = Database.get_audio_stream_for_phoneme(jellyfish.stimulus.Phoneme)
audio_player.play()
await get_tree().create_timer(1).timeout
jellyfish.delete()
# Play the pressed jellyfish phoneme
if jellyfish.stimulus and jellyfish.stimulus.Phoneme:
await _play_phoneme(jellyfish.stimulus.Phoneme)
# Remove the jellyfish
await jellyfish.delete()
# Handle the blocking array
if jellyfish in blocking_jellyfish:
blocking_jellyfish.erase(jellyfish)
# Replay the current stimulus
if not is_right:
_play_stimulus()
_play_current_stimulus_phoneme()
# ------------ UI Callbacks ------------
func _on_current_progression_changed() -> void:
if current_progression > 0:
audio_player.stream = Database.get_audio_stream_for_phoneme(stimuli[current_progression % stimuli.size()].Phoneme)
audio_player.play()
_play_current_stimulus_phoneme()
func _play_stimulus() -> void:
audio_player.stream = Database.get_audio_stream_for_phoneme(stimuli[current_progression % stimuli.size()].Phoneme)
audio_player.play()
if audio_player.playing:
await audio_player.finished
await _play_current_stimulus_phoneme()
@@ -11,10 +11,10 @@
[node name="JellyfishMinigame" instance=ExtResource("1_hauef")]
script = ExtResource("2_gnjlp")
lesson_nb = 10
difficulty = 0
max_number_of_lives = 5
max_progression = 8
lesson_nb = 12
difficulty = 4
max_number_of_lives = 3
max_progression = 9
intro_kalulu_speech = ExtResource("3_6sswr")
help_kalulu_speech = ExtResource("2_7li38")
win_kalulu_speech = ExtResource("3_ar7nu")
+18
View File
@@ -101,6 +101,24 @@ func get_GP_before_and_for_lesson(lesson_nb: int, distinct: bool) -> Array:
return db.query_result
func get_vowels_for_lesson(lesson_nb: int) -> Array:
var query: = "Select Grapheme, Phoneme, LessonNb FROM GPs
INNER JOIN GPsInLessons ON GPsInLessons.GPID = GPs.ID
INNER JOIN Lessons ON Lessons.ID = GPsInLessons.LessonID AND Lessons.LessonNb == ?
WHERE Type=1"
db.query_with_bindings(query, [lesson_nb])
return db.query_result
func get_vowels_before_lesson(lesson_nb: int) -> Array:
var query: = "Select Grapheme, Phoneme, LessonNb FROM GPs
INNER JOIN GPsInLessons ON GPsInLessons.GPID = GPs.ID
INNER JOIN Lessons ON Lessons.ID = GPsInLessons.LessonID AND Lessons.LessonNb < ?
WHERE Type=1"
db.query_with_bindings(query, [lesson_nb])
return db.query_result
func get_GP_from_word(word: String) -> Array:
db.query_with_bindings("SELECT Grapheme, Phoneme FROM Words INNER JOIN GPsInWords ON Words.ID = GPsInWords.WordID AND Words.Word=? INNER JOIN GPs WHERE GPS.ID = GPsInWords.GPID ORDER BY Position", [word])
return db.query_result
+6 -4
View File
@@ -1,17 +1,19 @@
extends Node
@onready var music_player := $MusicPlayer
@onready var music_player : AudioStreamPlayer = $MusicPlayer
const main_menu_music := preload("res://assets/menus/main/ui_title_card_music.mp3")
func _ready():
music_player.stream = main_menu_music
music_player.play()
play(main_menu_music)
func _on_music_player_finished():
music_player.stream_paused = false
music_player.play()
func play_music(music : AudioStream):
func play(music : AudioStream):
music_player.stream = music
music_player.play()
func stop():
music_player.stop()
+1 -1
View File
@@ -1,4 +1,4 @@
extends Node2D
extends Control
@onready var animation_player: = $AnimationPlayer
+3 -1
View File
@@ -223,7 +223,9 @@ _data = {
[sub_resource type="CanvasItemMaterial" id="CanvasItemMaterial_3qhub"]
blend_mode = 1
[node name="HighlightFX" type="Node2D"]
[node name="HighlightFX" type="Control"]
layout_mode = 3
anchors_preset = 0
script = ExtResource("1_uj18s")
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]