conductor/scripts/musician.gd
2026-03-16 00:25:37 -04:00

133 lines
3.2 KiB
GDScript

#@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
#input_prompt.texture = solid_texture
func _pause() -> void:
play("idle")
audio.stop()
beat_timer.stop()
light.visible = false
is_playing_music = false
#input_prompt.texture = outline_texture
## 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