Files
Kalulu/sources/minigames/frog/frog.gd
T
2026-02-20 15:01:52 +01:00

145 lines
4.3 KiB
GDScript

class_name Frog
extends Control
signal jumped()
const JUMP_SOUNDS: Array[AudioStreamMP3] = [
preload("res://assets/minigames/frog/audio/frog_jump_random_01.mp3"),
preload("res://assets/minigames/frog/audio/frog_jump_random_02.mp3"),
preload("res://assets/minigames/frog/audio/frog_jump_random_03.mp3"),
preload("res://assets/minigames/frog/audio/frog_jump_random_04.mp3"),
preload("res://assets/minigames/frog/audio/frog_jump_random_05.mp3"),
]
const FROG_SOUNDS: Array[AudioStreamMP3] = [
preload("res://assets/minigames/frog/audio/frog_random_01.mp3"),
preload("res://assets/minigames/frog/audio/frog_random_02.mp3"),
preload("res://assets/minigames/frog/audio/frog_random_03.mp3"),
preload("res://assets/minigames/frog/audio/frog_random_04.mp3"),
preload("res://assets/minigames/frog/audio/frog_random_05.mp3"),
]
const FROG_SPLASH: AudioStreamMP3 = preload("res://assets/minigames/frog/audio/frog_splash.mp3")
const FROG_BUBBLE: AudioStreamMP3 = preload("res://assets/minigames/frog/audio/frog_bubble.mp3")
const JUMP_HEIGHT: float = 220.0
var blink_counter: int = 0
var blink_delay: int = 3
var blink_random: int = 3
var last_valid_position: Vector2
@onready var animated_sprite: AnimatedSprite2D = $AnimatedSprite2D
@onready var audio_player: AudioStreamPlayer2D = $AudioStreamPlayer2D
func jump_to(destination: Vector2) -> void:
animated_sprite.play("jump")
var start: Vector2 = global_position
var end: Vector2 = destination
var duration: float = Utils.get_animation_duration(animated_sprite, "jump")
# Apex is above the higher of the two points (smaller Y is higher in 2D)
var apex_y: float = min(start.y, end.y) - JUMP_HEIGHT
var tween: Tween = create_tween()
tween.tween_method(
func(time: float) -> void:
# X: strictly linear over the whole jump
var horizontal: float = lerpf(start.x, end.x, time)
# Y: fast takeoff, slow near apex, then accelerating fall
var vertical: float
var weight: float
if time < 0.5:
weight = time / 0.5
weight = ease(weight, -2.5) # ease-out: strong impulse at start
vertical = lerpf(start.y, apex_y, weight)
else:
weight = (time - 0.5) / 0.5
weight = ease(weight, 2.5) # ease-in: accelerates on descent
vertical = lerpf(apex_y, end.y, weight)
global_position = Vector2(horizontal, vertical),
0.0,
1.0,
duration
).set_trans(Tween.TRANS_LINEAR)
_play_jump_sound()
func defeat() -> void:
animated_sprite.play("flip_sad")
await animated_sprite.animation_finished
animated_sprite.play("defeat")
audio_player.stream = FROG_SPLASH
audio_player.play()
await animated_sprite.animation_finished
await audio_player.finished
func success() -> void:
animated_sprite.play("success")
last_valid_position = global_position
func win() -> void:
await flip_happy()
animated_sprite.play("idle_front")
func flip_happy() -> void:
animated_sprite.play("flip_happy")
await animated_sprite.animation_finished
func _play_jump_sound() -> void:
audio_player.stream = JUMP_SOUNDS[randi() % JUMP_SOUNDS.size()]
audio_player.play()
func play_frog_sound() -> void:
var rand: float = randf()
if rand <= 0.75:
audio_player.stream = FROG_SOUNDS[randi() % FROG_SOUNDS.size()]
audio_player.play()
func appear() -> void:
global_position = last_valid_position
animated_sprite.play("appear")
audio_player.stream = FROG_BUBBLE
audio_player.play()
await animated_sprite.animation_finished
await flip_happy()
animated_sprite.play("idle_side")
func _on_animated_sprite_2d_animation_finished() -> void:
match animated_sprite.animation:
"idle_front":
blink_counter -= 1
if blink_counter <= 0:
blink_counter = blink_delay + randi_range(0, blink_random)
animated_sprite.play("idle_front_blink")
else:
animated_sprite.play("idle_front")
"idle_front_blink":
animated_sprite.play("idle_front")
"idle_side":
blink_counter -= 1
if blink_counter <= 0:
blink_counter = blink_delay + randi_range(0, blink_random)
animated_sprite.play("idle_side_blink")
else:
animated_sprite.play("idle_side")
"idle_side_blink":
animated_sprite.play("idle_side")
"success":
animated_sprite.play("idle_side")
"jump":
animated_sprite.play("idle_side")
jumped.emit()
func idle_boss() -> void:
animated_sprite.play("idle_front")
animated_sprite.stop()
func victory_boss() -> void:
animated_sprite.play("idle_front")