tojam20-elevator/scenes/pulse.gd

126 lines
3.4 KiB
GDScript

extends Node
const TRAIL_GHOSTS := 8
const TRAIL_SPACING := 3.0
const TRAIL_ALPHAS := [0.5, 0.42, 0.34, 0.27, 0.2, 0.14, 0.09, 0.05]
const GLOW_PADDING := Vector2(6, 6)
const GLOW_COLOR := Color(1, 0.3, 0.3, 0.35)
var pulse_speed := 80.0
var pulse_speed_initial := 80.0
var pulse_speed_per_floor := 8.0
var pulse_speed_increase := 15.0
var pulse_x := 0.0
var pulse_active := false
var pulse_gap := 1.0
var pulse_gap_decrease := 0.05
var pulse_gap_min := 0.3
var pulses_blocked := 0
var _sweep_line: ColorRect
var _target_zone: ColorRect
var _perfect_zone: ColorRect
var _screen_width: float
var _glow: ColorRect
var _trail: Array[ColorRect] = []
signal pulse_started(duration: float)
signal pulse_blocked
signal pulse_blocked_perfect
signal pulse_escaped
func configure(sweep_line: ColorRect, target_zone: ColorRect, perfect_zone: ColorRect, screen_width: float):
_sweep_line = sweep_line
_target_zone = target_zone
_perfect_zone = perfect_zone
_screen_width = screen_width
_build_visuals()
func _build_visuals():
var host: Control = _sweep_line.get_parent() as Control
_glow = ColorRect.new()
_glow.color = GLOW_COLOR
_glow.size = Vector2(_sweep_line.size.x + GLOW_PADDING.x * 2, _sweep_line.size.y + GLOW_PADDING.y * 2)
_glow.visible = false
host.add_child(_glow)
host.move_child(_glow, 0)
for i in TRAIL_GHOSTS:
var ghost := ColorRect.new()
ghost.color = Color(_sweep_line.color.r, _sweep_line.color.g, _sweep_line.color.b, TRAIL_ALPHAS[i])
ghost.size = _sweep_line.size
ghost.visible = false
host.add_child(ghost)
host.move_child(ghost, 0)
_trail.append(ghost)
func start_floor(floor_num: int):
pulses_blocked = 0
var floors_descended = EventBus.STARTING_FLOOR - floor_num
pulse_speed = pulse_speed_initial + floors_descended * pulse_speed_per_floor
pulse_gap = 1.0
pulse_active = false
func launch():
pulse_x = 0.0
pulse_active = true
_sweep_line.visible = true
_sweep_line.position.x = 0
_glow.visible = true
for ghost in _trail:
ghost.visible = true
pulse_started.emit(_screen_width / pulse_speed)
func attempt_block() -> bool:
if not pulse_active:
return false
var bz_left = _target_zone.position.x
var bz_right = _target_zone.position.x + _target_zone.size.x
if pulse_x >= bz_left and pulse_x <= bz_right:
var perfect_left = bz_left + _perfect_zone.position.x
var perfect_right = perfect_left + _perfect_zone.size.x
var was_perfect = pulse_x >= perfect_left and pulse_x <= perfect_right
pulse_active = false
pulses_blocked += 1
pulse_speed += pulse_speed_increase
pulse_gap = max(pulse_gap - pulse_gap_decrease, pulse_gap_min)
_hide_visuals()
pulse_blocked.emit()
if was_perfect:
pulse_blocked_perfect.emit()
return true
else:
pulse_active = false
_hide_visuals()
pulse_escaped.emit()
return false
func get_pulse_gap() -> float:
return pulse_gap
func stop():
pulse_active = false
_hide_visuals()
func _process(delta):
if not pulse_active:
return
pulse_x += pulse_speed * delta
_sweep_line.position.x = pulse_x
_glow.position = Vector2(pulse_x - GLOW_PADDING.x, _sweep_line.position.y - GLOW_PADDING.y)
for i in _trail.size():
var gx = pulse_x - (i + 1) * TRAIL_SPACING
_trail[i].visible = gx >= 0
_trail[i].position = Vector2(gx, _sweep_line.position.y)
if pulse_x >= _screen_width:
pulse_active = false
_hide_visuals()
pulse_escaped.emit()
func _hide_visuals():
if _sweep_line:
_sweep_line.visible = false
if _glow:
_glow.visible = false
for ghost in _trail:
ghost.visible = false