extends WordsMinigame signal can_spawn_turtle() const TURTLE_SCENE: PackedScene = preload("res://sources/minigames/turtles/turtle.tscn") # Defines the maximum number of turtles visible on screen const MAX_TURTLE_COUNT: int = 5 # Defines the minimum distance between turtles when spawning them const MIN_DISTANCE: int = 500 var difficulty_settings: Array[DifficultySettings] = [ DifficultySettings.new(.75, 200., 4.), DifficultySettings.new(.66, 250., 3.5), DifficultySettings.new(.33, 300., 3.), DifficultySettings.new(.25, 333., 2.5), DifficultySettings.new(.25, 366., 2.) ] var settings: DifficultySettings var turtle_count: int = 0: set(value): if turtle_count >= MAX_TURTLE_COUNT and value < MAX_TURTLE_COUNT: can_spawn_turtle.emit() turtle_count = value var stimulus_spawned: bool = false var color: Turtle.Colors @onready var water: Water = $GameRoot/Water @onready var island: Island = $GameRoot/Island @onready var turtles: Node = %Turtles @onready var spawn_timer: Timer = $GameRoot/SpawnTimer @onready var spawn_points_container: Node2D = $GameRoot/SpawnPoints @onready var spawn_location: Node2D @onready var crab: AnimatedSprite2D = %CrabAnimatedSprite2D func _start() -> void: super() fireworks.set_colors([Color("#ffd366"), Color("#bca4ff"), Color("#f5a8c8")]) # Find and set the parameters of the minigame, like the number of lives or the victory conditions. func _setup_minigame() -> void: super._setup_minigame() pick_random_color() # Sets up the current settings settings = difficulty_settings[difficulty] if not settings: return # Sets up the island for the first word island.stimulus = self._get_current_stimulus() # Sets up the timer spawn_timer.wait_time = settings.spawn_rate for stimulus: Dictionary in stimuli: Log.trace("TurtleMinigame: %s" % stimulus.Word) crab.play("idle_claws") func pick_random_color() -> void: color = randi_range(0, Turtle.Colors.size() - 1) as Turtle.Colors func _highlight() -> void: for turtle: Turtle in turtles.get_children(): if self._is_gp_right(turtle.gp): turtle.highlight(true) func _stop_highlight() -> void: for turtle: Turtle in turtles.get_children(): turtle.highlight(false) func _play_turtle_phoneme(gp: Dictionary) -> void: if gp and gp.has("Phoneme"): await audio_player.play_gp(gp) func _clear_turtles() -> void: for turtle: Turtle in turtles.get_children(): turtle.disappear() #region Connections func _on_spawn_timer_timeout() -> void: Log.trace("TurtleMinigame: Spawn timer timeout") # Checks if there are too many turtle, and wait for one to despawn if turtle_count >= MAX_TURTLE_COUNT: Log.trace("TurtleMinigame: Waiting for possibility to spawn more turtles") await can_spawn_turtle Log.trace("TurtleMinigame: Spawn a turtle") var turtle: Turtle = TURTLE_SCENE.instantiate() # Pick a position to spawn the turtle var position_found: bool = false while not position_found: spawn_location = spawn_points_container.get_children().pick_random() var all_position_ok: bool = true # Check if there are other turtles nearby for other_turtle: Turtle in turtles.get_children(): if other_turtle.position.distance_squared_to(spawn_location.position) < MIN_DISTANCE * MIN_DISTANCE: all_position_ok = false break position_found = all_position_ok turtle.position = spawn_location.position turtle.velocity = settings.velocity turtle.pressed.connect(_play_turtle_phoneme) turtle.animation_changed.connect(water.spawn_water_ring) turtle.tree_exited.connect( func() -> void: turtle_count -= 1 if stimulus_spawned and _is_gp_right(turtle.gp): stimulus_spawned = false ) turtles.add_child(turtle) turtle.color = color # Set the direction of the turtle var random_offset: float = deg_to_rad(randf_range(-5, 5)) turtle.direction = Vector2.DOWN.rotated(spawn_location.rotation + random_offset).normalized() # Define if the turtle is a stimulus or a distraction var is_stimulus: bool = not stimulus_spawned and randf() < settings.stimuli_ratio if is_stimulus: turtle.gp = _get_gp() if is_highlighting: turtle.highlight(true) stimulus_spawned = true else: turtle.gp = _get_distractor() # Increment the count turtle_count += 1 # Restarts timer spawn_timer.start() func _on_island_area_entered(area: Area2D) -> void: # Get the turtle that landed on the island var turtle: Turtle = area.owner as Turtle if not turtle: return # Log the answer _log_new_response_and_score(turtle.gp) # Disable the island collisions island.set_enabled(false) # Check if the turtle is a distractor or the awaited GP if _is_gp_right(turtle.gp): # Handles the stimulus spawned status stimulus_spawned = false # Stop the spawning spawn_timer.stop() # Play the right animation await turtle.right() # Clear all the turtles _clear_turtles() # Update the island island.progress = current_word_progression + 1 # Play the GP await audio_player.play_gp(_get_gp()) # Update the word progression current_word_progression += 1 else: # Play the wrong animation await turtle.wrong() # Clear the turtle turtle.disappear() # Play the GP await audio_player.play_gp(turtle.gp) # Update the lives current_lives -= 1 # Re-enable the island collisions island.set_enabled(true) func _on_current_word_progression_changed() -> void: super() # Spawn a turtle and restarts the timer _on_spawn_timer_timeout() func _on_current_progression_changed() -> void: # Stop the spawning spawn_timer.stop() pick_random_color() # Replay the stimulus await get_tree().create_timer(time_between_words/2).timeout audio_player.play_word(_get_previous_stimulus().Word as String) await get_tree().create_timer(time_between_words/2).timeout # Starts a new round super() # Reset island island.stimulus = self._get_current_stimulus() # Restarts the spawning spawn_timer.start() func _win() -> void: crab.play("victory_claws") super() #endregion class DifficultySettings: var stimuli_ratio: float = 0.75 var velocity: float = 250. var spawn_rate: float = 4. func _init(p_stimuli_ratio: float, p_velocity: float, p_spawn_rate: float) -> void: stimuli_ratio = p_stimuli_ratio velocity = p_velocity spawn_rate = p_spawn_rate