#@tool #@icon(icon_path: String) class_name Musician extends AnimatedSprite2D ## Documentation comments #signal #enum #const @export_group("Input Textures") @export var solid_texture: Texture2D @export var outline_texture: Texture2D @export var beats_per_boost: int = 4 @export var song_tempo: int = 120 @export_enum("sample", "viol", "cello", "bass", "ready") var input_action: String var decay_length: float var decay_rate: float var is_active: bool = false var is_boosted: bool var is_over_boosted: bool = false var seconds_per_beat: float var useconds_per_beat: int @onready var audio: AudioStreamPlayer2D = %Audio @onready var light: PointLight2D = %Light @onready var occluder: LightOccluder2D = %Occluder @onready var input_prompt: Sprite2D = %InputPrompt @onready var volume_bar: ProgressBar = %VolumeBar @onready var boost_timer: Timer = %BoostTimer ## OVERRIDES func _ready() -> void: light.visible = false _connect_signals() input_prompt.texture = outline_texture seconds_per_beat = 60.0/float(song_tempo) decay_length = beats_per_boost * seconds_per_beat print("this musician's boosts will last %s seconds" % decay_length) boost_timer.wait_time = decay_length decay_rate = 80.0 / decay_length print("so the volume will drop by %s db per second" % decay_rate) func _process(delta: float) -> void: if is_over_boosted: distort_pitch(sin(Time.get_ticks_msec())) if is_active and not is_boosted: drop_volume(decay_rate * delta) volume_bar.value = audio.volume_db func _unhandled_input(event: InputEvent) -> void: if event.is_action_pressed("play_pause"): play_pause() if event.is_action_pressed(input_action): boost_volume() ## CORE func boost_volume() -> void: if is_boosted: is_over_boosted = true audio.volume_db = 0.0 is_boosted = true boost_timer.start() func distort_pitch(distortion: float) -> void: print("distorting by %s" % distortion) audio.pitch_scale += distortion print("pitch scale is %s" % audio.pitch_scale) func drop_volume(d_r: float) -> void: audio.volume_db -= d_r func play_pause() -> void: if is_active: play("idle") audio.stop() light.visible = false is_active = false input_prompt.texture = outline_texture else: play("default") audio.play() if not is_boosted: is_boosted = true boost_timer.start() light.visible = true is_active = true input_prompt.texture = solid_texture ## PRIVATE/HELPER func _connect_signals() -> void: boost_timer.connect("timeout", on_boost_timer_timeout) audio.connect("finished", play_pause) ## RECEIVERS func on_boost_timer_timeout() -> void: print("boost over") boost_timer.stop() is_boosted = false is_over_boosted = false audio.pitch_scale = 1.0 ## SETTERS/GETTERS