CHALLENGE 2: A Damage Flash Driven by the Health Signal ==================================================================== TASK ---- Add an AnimationPlayer to a Sprite2D with a short "flash" animation (e.g. briefly changing modulate to red and back). Connect it to Chapter 7's health_changed signal so the sprite flashes every time take_damage() is called. SETUP - the "flash" animation ---------------------------------- 1. Add an AnimationPlayer as a sibling (or child) of the Sprite2D you want to flash. 2. In the Animation panel, create a new animation named "flash", about 0.3 seconds long. 3. Select the Sprite2D, and with the animation timeline open, add a keyframe for its "modulate" property at time 0.0 (white, the default), one at 0.1s (red), and one at 0.3s (back to white). SCENE STRUCTURE ---------------- Root (Node2D) |-- Health (Node) <- health.gd, from Chapter 7 |-- PlayerSprite (Sprite2D) |-- AnimationPlayer <- the "flash" animation |-- FlashController.gd <- this script SOLUTION CODE (attached to a Node under PlayerSprite, or PlayerSprite itself) ------------------------------------------------------------------------------------ extends Node func _ready() -> void: get_parent().get_parent().get_node("Health").health_changed.connect(_on_health_changed) func _on_health_changed(current: int, max_health: int) -> void: get_parent().get_node("AnimationPlayer").play("flash") (A simpler, common alternative is to attach this logic directly to the Sprite2D itself, in which case $AnimationPlayer.play("flash") can be used directly, exactly as shown in the chapter.) WHY THIS WORKS AS AN ANSWER ---------------------------- This connects to health_changed the same way every other listener in this course has (Chapter 7's Challenge 3, Chapter 8's health bar) - the sprite doesn't know or care why health changed, only that it did, and reacts by playing its own "flash" animation every single time the signal fires, regardless of whether current went up or down. $AnimationPlayer.play("flash") triggers the entire keyframed sequence recorded in the editor with one call - the AnimationPlayer itself handles smoothly interpolating the Sprite2D's modulate color from white to red and back over the recorded 0.3 seconds, with no manual per-frame color-blending code needed in the script at all. Because this fires from health_changed rather than being called directly from take_damage(), the exact same flash would also trigger correctly if some other, entirely different part of the game later called take_damage() through a completely different code path - the flash is a property of "health changed," not of any one specific call site.