133 lines
3.2 KiB
GDScript
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
|