Files
Kalulu/sources/minigames/turtles/turtles_minigame.gd
T
2026-01-26 13:48:59 +01:00

242 lines
6.2 KiB
GDScript

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