Files
Kalulu/sources/minigames/monkeys/monkeys_minigame.gd
T

248 lines
7.9 KiB
GDScript

extends WordsMinigame
enum Audio {
SEND_TO_KING,
SEND_TO_PLANK,
SEND_TO_MONKEY,
}
const MONKEY_SCENE: PackedScene = preload("res://sources/minigames/monkeys/monkey.tscn")
const AUDIO_STREAMS: Array[AudioStreamMP3] = [
preload("res://assets/minigames/monkeys/audio/monkey_sendcoco.mp3"),
preload("res://assets/minigames/monkeys/audio/monkey_sendcoco_right.mp3"),
preload("res://assets/minigames/monkeys/audio/monkey_sendcoco_wrong.mp3"),
]
@export var throw_to_king_duration: float = 1.2
@export var throw_to_monkey_duration: float = 0.4
@export var throw_to_plank_duration: float = 0.8
var difficulty_settings: Array[DifficultySettings] = [
DifficultySettings.new(1),
DifficultySettings.new(1),
DifficultySettings.new(1),
DifficultySettings.new(2),
DifficultySettings.new(2)
]
var monkeys: Array[Monkey] = []
var is_locked: bool = true:
set(value):
is_locked = value
for monkey: Monkey in monkeys:
monkey.locked = value
@onready var monkeys_node: Control = $GameRoot/Monkeys
@onready var possible_positions_parent: Sprite2D = $GameRoot/PalmTreeMonkeys
@onready var king: KingMonkey = $GameRoot/PlamTreeKing/KingMonkey
@onready var word_label: RichTextLabel = $GameRoot/TextPlank/Label
@onready var parabola_summit: Control = $GameRoot/ParabolaSummit
@onready var text_plank: Sprite2D = $GameRoot/TextPlank
# Find and set the parameters of the minigame, like the number of lives or the victory conditions.
func _setup_minigame() -> void:
Log.trace("MonkeysMinigame: SetupMinigame")
super()
var settings: DifficultySettings = difficulty_settings[difficulty]
for index: int in range(settings.distractors_count + 1):
await get_tree().process_frame
Log.trace("MonkeysMinigame: SetupMinigame: Instantiate new monkey")
var monkey: Monkey = MONKEY_SCENE.instantiate()
monkeys_node.add_child(monkey)
monkeys.append(monkey)
var pos: Node2D = possible_positions_parent.get_child(index) as Node2D
monkey.global_position = pos.global_position
monkey.pressed.connect(_on_monkey_pressed.bind(monkey))
monkey.dragged_into_self.connect(_on_monkey_pressed.bind(monkey))
monkeys_node.set_drag_forwarding(
# drag_func
func(_at_position: Vector2) -> Variant:
return null,
# can_drop_func
func(_at_position: Vector2, _data: Variant) -> bool:
return true,
# drop_func
func(at_position: Vector2, data: Variant) -> void:
if (at_position - data.start_position).x < 0:
_on_coconut_thrown(data.monkey as Monkey)
)
_update_label(0)
# Pre-warm particle shaders to avoid stutter on first coconut explosion
await get_tree().process_frame
await monkeys[0].coconut.broken_coconut_fx.warm_up()
func _start() -> void:
super()
fireworks.set_colors([Color("#ffd366"), Color("#ffbf94"), Color("#7fc8ff")])
func _highlight() -> void:
for monkey: Monkey in monkeys:
if _is_gp_right(monkey.stimulus):
monkey.highlight()
func _update_label(progress: int, color: bool = true) -> void:
var gps_count: int = self._get_current_stimulus().GPsCount as int
word_label.text = ""
for index: int in range(gps_count):
if progress > index or progress == gps_count:
if color and progress == index + 1:
word_label.text += "[color=%s]" % Minigame.LABEL_COLOR_WIN.to_html()
word_label.text += self._get_current_stimulus().GPs[index].Grapheme
if color and progress == index + 1:
word_label.text += "[/color]"
else:
word_label.text += "_"
Log.info(word_label.text)
func _stop_highlight() -> void:
for monkey: Monkey in monkeys:
monkey.stop_highlight()
func _play_monkey_stimulus(monkey: Monkey) -> void:
var coroutine: Coroutine = Coroutine.new()
coroutine.add_future(monkey.talk)
audio_player.play_gp(monkey.stimulus)
if audio_player.playing:
coroutine.add_future(audio_player.finished)
await coroutine.join_all()
func _get_coconut_from_monkey_to_king(monkey: Monkey) -> Node2D:
monkey.stop_highlight()
await monkey.play("start_throw")
monkey.play("finish_throw")
audio_player.stream = AUDIO_STREAMS[Audio.SEND_TO_KING]
audio_player.play()
var coconut: Coconut = monkey.coconut.duplicate()
monkey.coconut.hide()
game_root.add_child(coconut)
coconut.text = monkey.coconut.text
coconut.global_transform = monkey.coconut.global_transform
var tween: Tween = create_tween()
tween.set_parallel()
tween.tween_property(coconut, "global_position:x", (coconut.global_position.x + king.catch_position.global_position.x) / 2, throw_to_king_duration / 2).set_trans(Tween.TRANS_LINEAR)
tween.tween_property(coconut, "global_position:y", parabola_summit.global_position.y, throw_to_king_duration / 2).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_OUT)
await tween.finished
tween = create_tween()
tween.set_parallel()
tween.tween_property(coconut, "global_position:x", king.catch_position.global_position.x, throw_to_king_duration / 2).set_trans(Tween.TRANS_LINEAR)
tween.tween_property(coconut, "global_position:y", king.catch_position.global_position.y, throw_to_king_duration / 2).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_IN)
await tween.finished
await king.catch(coconut)
return coconut
#region Connections
func _on_monkey_pressed(monkey: Monkey) -> void:
is_locked = true
await _play_monkey_stimulus(monkey)
is_locked = false
func _on_coconut_thrown(monkey: Monkey) -> void:
# Log the answer
_log_new_response_and_score(monkey.stimulus)
is_locked = true
var coconut: Coconut = await _get_coconut_from_monkey_to_king(monkey)
# All monkeys talk but the sound is from a specific monkey
var coroutine: Coroutine = Coroutine.new()
coroutine.add_future(king.play.bind("read"))
coroutine.add_future(_play_monkey_stimulus.bind(monkey))
await coroutine.join_all()
if _is_gp_right(monkey.stimulus):
await king.play("start_right")
audio_player.stream = AUDIO_STREAMS[Audio.SEND_TO_PLANK]
audio_player.play()
king.play("finish_right")
var tween: Tween = create_tween()
tween.tween_property(coconut, "global_position:y", text_plank.global_position.y, throw_to_plank_duration).set_trans(Tween.TRANS_LINEAR)
await tween.finished
_update_label(current_word_progression + 1)
await coconut.explode()
_update_label(current_word_progression + 1, false)
current_word_progression += 1
else:
await king.play("start_wrong")
audio_player.stream = AUDIO_STREAMS[Audio.SEND_TO_MONKEY]
audio_player.play()
king.play("finish_wrong")
var tween: Tween = create_tween()
tween.tween_property(coconut, "global_position", monkey.hit_position.global_position, throw_to_monkey_duration).set_trans(Tween.TRANS_LINEAR)
await tween.finished
await monkey.hit(coconut)
current_lives -= 1
is_locked = false
func _on_current_word_progression_changed() -> void:
super()
var ind_good: int = randi_range(0, monkeys.size() - 1)
for index: int in range(monkeys.size()):
var monkey: Monkey = monkeys[index]
if index == ind_good:
monkey.stimulus = _get_gp()
else:
monkey.stimulus = _get_distractor()
monkey.stunned = false
monkey.coconut.show()
var coroutine: Coroutine = Coroutine.new()
if audio_player.playing:
coroutine.add_future(audio_player.finished)
for monkey: Monkey in monkeys:
monkey.coconut.hide()
coroutine.add_future(monkey.play.bind("grab"))
await coroutine.join_all()
is_locked = false
func _on_current_progression_changed() -> void:
# Replay the stimulus
await get_tree().create_timer(time_between_words/2).timeout
var coroutine: Coroutine = Coroutine.new()
for monkey: Monkey in monkeys:
coroutine.add_future(monkey.talk)
audio_player.play_word(_get_previous_stimulus().Word as String)
if audio_player.playing:
coroutine.add_future(audio_player.finished)
await coroutine.join_all()
await get_tree().create_timer(time_between_words/2).timeout
# Starts a new round
@warning_ignore("redundant_await")
await super()
# Reset the label
_update_label(0)
is_locked = false
#endregion
class DifficultySettings:
var distractors_count: int = 1
func _init(p_distractors_count: int) -> void:
distractors_count = p_distractors_count