conductor/scripts/musician.gd

111 lines
2.7 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 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