feat(sprint-14): add Balloon pop/respawn state machine
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
## Balloon — tap to pop, auto-respawns after a delay.
|
||||
class_name Balloon extends Node2D
|
||||
|
||||
enum State { IDLE, POPPING, POPPED, RESPAWNING }
|
||||
|
||||
const POP_DURATION: float = 0.15
|
||||
const RESPAWN_DURATION: float = 0.30
|
||||
const RESPAWN_DELAY: float = 5.0
|
||||
const BUTTON_HALF_SIZE: float = 20.0
|
||||
|
||||
var _state: State = State.IDLE
|
||||
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
if _state != State.IDLE:
|
||||
return
|
||||
if not event is InputEventScreenTouch:
|
||||
return
|
||||
var touch: InputEventScreenTouch = event as InputEventScreenTouch
|
||||
if not touch.pressed:
|
||||
return
|
||||
var local: Vector2 = to_local(touch.position)
|
||||
if abs(local.x) > BUTTON_HALF_SIZE or abs(local.y) > BUTTON_HALF_SIZE:
|
||||
return
|
||||
_start_pop()
|
||||
|
||||
|
||||
func _start_pop() -> void:
|
||||
AudioManager.play_sfx("object_tap")
|
||||
_state = State.POPPING
|
||||
var tween: Tween = create_tween()
|
||||
tween.set_ease(Tween.EASE_IN)
|
||||
tween.set_trans(Tween.TRANS_BACK)
|
||||
tween.tween_property(self, "scale", Vector2.ZERO, POP_DURATION)
|
||||
tween.tween_callback(_on_pop_complete)
|
||||
|
||||
|
||||
func _on_pop_complete() -> void:
|
||||
_state = State.POPPED
|
||||
var tween: Tween = create_tween()
|
||||
tween.tween_interval(RESPAWN_DELAY)
|
||||
tween.tween_callback(_start_respawn)
|
||||
|
||||
|
||||
func _start_respawn() -> void:
|
||||
_state = State.RESPAWNING
|
||||
var tween: Tween = create_tween()
|
||||
tween.set_ease(Tween.EASE_OUT)
|
||||
tween.set_trans(Tween.TRANS_BACK)
|
||||
tween.tween_property(self, "scale", Vector2.ONE, RESPAWN_DURATION)
|
||||
tween.tween_callback(_on_respawn_complete)
|
||||
|
||||
|
||||
func _on_respawn_complete() -> void:
|
||||
_state = State.IDLE
|
||||
@@ -0,0 +1,29 @@
|
||||
## Tests for Balloon — state machine transitions.
|
||||
extends GutTest
|
||||
|
||||
var _balloon: Balloon
|
||||
|
||||
|
||||
func before_each() -> void:
|
||||
_balloon = Balloon.new()
|
||||
add_child_autofree(_balloon)
|
||||
|
||||
|
||||
func test_initial_state_is_idle() -> void:
|
||||
assert_eq(_balloon._state, Balloon.State.IDLE)
|
||||
|
||||
|
||||
func test_start_pop_transitions_to_popping() -> void:
|
||||
_balloon._start_pop()
|
||||
assert_eq(_balloon._state, Balloon.State.POPPING)
|
||||
|
||||
|
||||
func test_on_pop_complete_transitions_to_popped() -> void:
|
||||
_balloon._on_pop_complete()
|
||||
assert_eq(_balloon._state, Balloon.State.POPPED)
|
||||
|
||||
|
||||
func test_on_respawn_complete_transitions_to_idle() -> void:
|
||||
_balloon._state = Balloon.State.RESPAWNING
|
||||
_balloon._on_respawn_complete()
|
||||
assert_eq(_balloon._state, Balloon.State.IDLE)
|
||||
Reference in New Issue
Block a user