248 lines
7.9 KiB
GDScript
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
|