#@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 song_tempo: int = 120 @export_enum("whole:4", "half:2", "quarter:1") var boost_note_type: int @export_enum("sample", "viol", "cello", "bass", "execute") var input_action: String var beat_count: int = 0 var decay_length: float var decay_rate: float var is_playing_music: 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 beat_timer: Timer = %BeatTimer @onready var boost_timer: Timer = %BoostTimer @onready var beat_particles: CPUParticles2D = $BeatParticles ## OVERRIDES func _ready() -> void: light.visible = false _connect_signals() #input_prompt.texture = outline_texture seconds_per_beat = 60.0/float(song_tempo) beat_timer.wait_time = seconds_per_beat decay_length = boost_note_type * 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() if is_playing_music 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() -> void: audio.pitch_scale += randf_range(-0.001, 0.0001) func drop_volume(d_r: float) -> void: audio.volume_db -= d_r func play_pause() -> void: if not is_playing_music: _play() else: _pause() ## PRIVATE/HELPER func _connect_signals() -> void: boost_timer.connect("timeout", on_boost_timer_timeout) audio.connect("finished", play_pause) beat_timer.connect("timeout", on_beat_timer_timeout) func _play() -> void: play("default") audio.play() beat_timer.start() if not is_boosted: is_boosted = true boost_timer.start() light.visible = true is_playing_music = true func _pause() -> void: play("idle") audio.stop() beat_timer.stop() light.visible = false is_playing_music = false ## RECEIVERS func on_beat_timer_timeout() -> void: beat_count += 1 if beat_count % 4 == 0: beat_particles.color = Color.RED beat_particles.amount = 24 beat_particles.lifetime = 0.2 else: beat_particles.color = Color.WHITE beat_particles.amount = 8 beat_particles.lifetime = 0.15 beat_particles.restart() 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