feat(sprint-14): add Cake cut/reset state machine
This commit is contained in:
@@ -0,0 +1,56 @@
|
|||||||
|
## Cake — tap to cut a slice, slice auto-respawns after a delay.
|
||||||
|
class_name Cake extends Node2D
|
||||||
|
|
||||||
|
enum State { WHOLE, CUTTING, CUT, RESETTING }
|
||||||
|
|
||||||
|
const CUT_DURATION: float = 0.3
|
||||||
|
const RESET_DURATION: float = 0.3
|
||||||
|
const RESET_DELAY: float = 3.0
|
||||||
|
const BUTTON_HALF_WIDTH: float = 40.0
|
||||||
|
const BUTTON_HALF_HEIGHT: float = 20.0
|
||||||
|
|
||||||
|
var _state: State = State.WHOLE
|
||||||
|
|
||||||
|
|
||||||
|
func _input(event: InputEvent) -> void:
|
||||||
|
if _state != State.WHOLE:
|
||||||
|
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_WIDTH or abs(local.y) > BUTTON_HALF_HEIGHT:
|
||||||
|
return
|
||||||
|
_start_cutting()
|
||||||
|
|
||||||
|
|
||||||
|
func _start_cutting() -> void:
|
||||||
|
AudioManager.play_sfx("object_tap")
|
||||||
|
_state = State.CUTTING
|
||||||
|
var slice: Node2D = get_node_or_null("Slice") as Node2D
|
||||||
|
var tween: Tween = create_tween()
|
||||||
|
if slice != null:
|
||||||
|
tween.tween_property(slice, "modulate:a", 0.0, CUT_DURATION)
|
||||||
|
tween.tween_callback(_on_cut_complete)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_cut_complete() -> void:
|
||||||
|
_state = State.CUT
|
||||||
|
var tween: Tween = create_tween()
|
||||||
|
tween.tween_interval(RESET_DELAY)
|
||||||
|
tween.tween_callback(_start_reset)
|
||||||
|
|
||||||
|
|
||||||
|
func _start_reset() -> void:
|
||||||
|
_state = State.RESETTING
|
||||||
|
var slice: Node2D = get_node_or_null("Slice") as Node2D
|
||||||
|
var tween: Tween = create_tween()
|
||||||
|
if slice != null:
|
||||||
|
tween.tween_property(slice, "modulate:a", 1.0, RESET_DURATION)
|
||||||
|
tween.tween_callback(_on_reset_complete)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_reset_complete() -> void:
|
||||||
|
_state = State.WHOLE
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
## Tests for Cake — state machine transitions.
|
||||||
|
extends GutTest
|
||||||
|
|
||||||
|
const CakeScript = preload("res://scripts/objects/cake.gd")
|
||||||
|
|
||||||
|
var _cake: Node2D
|
||||||
|
|
||||||
|
|
||||||
|
func before_each() -> void:
|
||||||
|
_cake = CakeScript.new()
|
||||||
|
add_child_autofree(_cake)
|
||||||
|
|
||||||
|
|
||||||
|
func test_initial_state_is_whole() -> void:
|
||||||
|
assert_eq(_cake._state, CakeScript.State.WHOLE)
|
||||||
|
|
||||||
|
|
||||||
|
func test_start_cutting_transitions_to_cutting() -> void:
|
||||||
|
_cake._start_cutting()
|
||||||
|
assert_eq(_cake._state, CakeScript.State.CUTTING)
|
||||||
|
|
||||||
|
|
||||||
|
func test_on_cut_complete_transitions_to_cut() -> void:
|
||||||
|
_cake._on_cut_complete()
|
||||||
|
assert_eq(_cake._state, CakeScript.State.CUT)
|
||||||
|
|
||||||
|
|
||||||
|
func test_on_reset_complete_transitions_to_whole() -> void:
|
||||||
|
_cake._state = CakeScript.State.RESETTING
|
||||||
|
_cake._on_reset_complete()
|
||||||
|
assert_eq(_cake._state, CakeScript.State.WHOLE)
|
||||||
Reference in New Issue
Block a user